iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 22
1
自我挑戰組

非本科之30天Ruby / Rails學習筆記系列 第 22

Day22: 簡易Rails實作(下)

  • 分享至 

  • xImage
  •  

上次講到了Strong Parameters,今天我們就從Flash開始吧!

快閃訊息flash

在按下按鈕後,應該要有個訊息出現告知使用者是否有成功或失敗,並且只出現一次,這就是快閃訊息做的事。
在這個專案,我們希望如果 create 成功,會將網頁導向 首頁 並印出 "新增候選人成功!!",反之若失敗,則印出”新增候選人失敗!!” (一樣false還沒寫入)


#上略 
  def create
    clean_params = params.require(:candidate).permit(:name, :age, :policy, :party)
    @candidate = Candidate.new(clean_params)
  
    if @candidate.save
      flash[:notice] = "新增候選人成功!!"         #第7~8行可直接寫成 redirect_to root_path, notice: "新增候選人成功!!"
      redirect_to root_path
    else
      flash[:notice] = "新增候選人失敗!!"         #第10~11行可直接寫成 redirect_to root_path, notice: "新增候選人失敗!!"
      redirect_to root_path
    end
  end  
end

#並在index.html.erb檔加入

<%= flash[:notice] %>   印出"新增候選人成功!"

首頁印出候選人列表

想要在首頁做事情,那當然是去 index 做事,首先針對 candidate_controller.rb 裡的 index method寫入:

@candidates = Candidate.all

注意:這裡的實體變數故意列為"複數",因為是撈出全部候選人的資料

去抓所有使用者輸入的資料。
再來到 index.html.erb 利用each迴圈印出所有候選人的"姓名"。

<%= flash[:notice] %>
<h1>首頁:候選人列表</h1>

# <%%>不顯示在頁面
#<=%%>要顯示在頁面上

<ul>
  <% @candidates.each do |candidate| %>     #注意是@candidate"s"
    <li><%= candidate.name %></li>
  <% end %>
</ul>

<%= link_to '新增候選人', new_candidate_path, class: 'btn btn-danger btn-lg' %>

驗證資料

人打字總偶爾有肥手指、眼睛業障或看錯欄位的狀況發生,所以每個輸入的資料都需要做進一步的認證才能進入資料庫。

(總不可能候選人只有3歲吧!!!?)

還記得剛剛寫的 if else 判斷總是忽略 false 的話怎麼辦對吧? 如果不寫入以下程式碼的話,永遠不會進入到 else 的判斷,到 candidate.rb 裡新增:

class Candidate < ApplicationRecord
  validates :name, presence: true  
  #腦補眼鏡
  #validates (:name, {presence: true})  
  
  validates :age, numericality: { greater_than_or_equal_to: 40 }
  #腦補眼鏡
  #validates (:age, {numericality: { {greater_than_or_equal_to: 40} }})
end

姓名欄位: 有資料才會會回傳true ; 年紀欄位: 必須大於或等於40歲
其實我們再 create 中的 if else 判斷式寫的較不人性化,若今天使用者打錯某字跳出"新增候選人失敗!!",回到新增頁面後竟然還要重新打字,是不是太麻煩了? 所以我們要修正else後的輸出方式:


class CandidatesController < ApplicationController
  def index
    @candidate = Candidate.all
  end
  def new
    @candidate = Candidate.new
  end  
  def create
    clean_params = params.require(:candidate).permit(:name, :age, :policy, :party)
    @candidate = Candidate.new(clean_params)
  
    if @candidate.save
      flash[:notice] = "新增候選人成功!"
      redirect_to root_path
    else
      #原來寫法:flash[:notice] = "新增候選人失敗!"
      #原來寫法:redirect_to root_path
      render :new  # 借new.html.erb這個檔案,並不是上方的new方法!!!
    end
  end  
end

就解決了如果打錯字回到頁面後文字被洗掉的問題。

哪裡輸入錯誤?

若輸入錯誤的話,總要告訴使用者是哪裡輸入錯誤吧?
new.html.erb內新增判斷式,就會印出Rails內建的full_messages資料庫訊息:

<h1>新增候選人</h1>

<% if @candidate.errors.any? %>   #.errors.any? =>有錯誤嗎?
  <ul>
  <% @candidate.errors.full_messages.each do |message| %> # .full_messages => Rails內建的錯誤訊息資料庫
    <li><%= message %></li>
  <% end %>
  </ul>
<% end %>
<%= form_for(@candidate) do |form| %>
#下略....

查看候選人詳細資料

當然在看候選人的時候不可能只看名字吧?所以我們要做一個只要點選候選人姓名,就轉至候選人資料的頁面。
index.html.erb頁面:

#index.html.erb

<%= flash[:notice] %>
<h1>首頁:候選人列表</h1>
<!--
<ul>
  <% @candidate.each do |candidate| %>
    <li><%= candidate.name %></li>
  <% end %>
</ul> -->

<ul>
  <% @candidate.each do |candidate| %>
    <!--路徑需查 rails routes -->
    <li><%= link_to candidate.name, candidate_path(candidate.id) %></li>
  <% end %>
</ul>

<%= link_to '新增候選人', new_candidate_path, class: 'btn btn-danger btn-lg' %>

就會是可以點選的狀態了,能夠預期若按下候選人姓名會發生什麼事嗎?

因為我們還沒有建立在 show 方法:

def show
    @candidate = Candidate.find_by(id: params[:id])  
    #Candidate.find_by => Rails內建尋找相對應資料的方法
    #腦補眼鏡({id: params[:id]})
end 

({id: params[:id]}) :取params內key是:id的value當作外面id:的value
聽起來很像繞口令,讓我們一步一步拆開來看。

params本身是Hash的資料型態,也就是上面有敘述過的一大串資料:

{"utf8"=>"✓", "authenticity_token"=>"0OHbZ7WkDs8NsrNHK2s7Dd9BxkITn/qegeFtUcMmE5ANKKiaxmRCOiPuChEAoKh4ho/taDYBB7GvIhTG0a1IHw==", "candidate"=>{"name"=>"Louis", "party"=>"none", "age"=>"20", "policy"=>"Rails is Good"}, "commit"=>"Create Candidate", "controller"=>"candidates", "action"=>"create"}

上面有講過個例子,若我要拿到Louis,我需要寫params['candidate']['name'] 才能拿到對吧?

params['candidate']['name']
↓     ↓
({ id:  params[:id]})

假設 params = { id: 5, email: 'kk@5xruby.tw', name: 'Louis' }
find_by(id: params[:id], email: params[:email], name: params[:name])
find_by(        5      ,      kk@5xruby.tw    ,     Louis          )

這樣可以找到在候選人表格裡「id 是 5,而且 email 是 kk@5xruby.tw,而且 name 是 Louis」的候選人

這樣對應著看,應該有比較容易理解吧!!

但還是會出現錯誤(笑

記得也要在views建立 show.html.erb

<% if @candidate %>
  <h1><%= @candidate.name %></h1>
  <ul>
    <li>黨派: <%= @candidate.party%> </li>
    <li>年紀: <%= @candidate.age%> </li>
    <li>政見: <%= @candidate.policy%> </li>
  </ul>
<% else %>
  <h1>沒有這個人</h1>
<% end %>

就終於完成了簡易CRUD中的C跟R...

腦細胞少10%,皺褶增加0.001%

參考資料:

為你自己學Ruby on Rails

“The difference in winning and losing is most often…not quitting.”

— Walt Disney, Producer

本文同步發佈於: https://louiswuyj.tw/


上一篇
Day21: 簡易Rails實作(中)
下一篇
Day23: Rails中的N+1問題
系列文
非本科之30天Ruby / Rails學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
阿展展展
iT邦好手 1 級 ‧ 2020-01-18 05:48:35

候選人 /images/emoticon/emoticon37.gif

我要留言

立即登入留言