# RL-?? CRUD 投票功能 在既有CTRD中加入。 ## 第一階段=網頁連結 在View的網頁,連結根據路徑表的Helper。 ```ruby= <%= candidate.votes %> #看票數 <%= link_to "投票", vote_candidate_path(candidate.id) %> ``` ## 第二階段=路徑表 手動新增路徑表route ```ruby= get '/candidates/:id/vote', to: 'candidates#vote'' ``` 或建議在resources下用do end包住: 1. member 新增成員方法 ```ruby= resources :candidates do member do post :vote #投票 end end ``` 2. collection 新增方法,不帶ID ```ruby= resources :candidates do collection do post :vote #投票 get :vote_list #看投票列表 end end ``` ## 第三階段=做出「vote」 在Controller新增方法「vote」。 第3行也能寫成 @candidate.increment(:votes) ```ruby= def vote @candidate = Candidate.find_by(id: params[:id]) #抓出它 @candidate.votes = @candidate.votes + 1 #欄位名稱寫在db的schema裡 用a=a+1邏輯投票 @candidate.save #儲存它 end flash[:notice] = "投票完成" redirect_to '/candidates' ``` ## 投票紀錄表 ### 在Model 建立一個Model。 * 欄位包括候選人id(candidate_id:integer)、IP位址(ip_address) * 使用 candidate:references 也會指向id流水編號 * 時間戳記會自動產生,不用另外寫。 ```ruby= $rails g model VoteLog candidate:references ip_address ``` 兩個檔案("app/model"與"db/migrate"之下的)沒問題的話,開始實體化: ```ruby= $rails db:migrate ``` ### 在Controller 在原Vote方法中,新增一筆資料庫 * request.remote_ip 可以抓IP * 注意new方法只是暫存記憶體,要另外save儲存。建議用create。 ```ruby= VoteLog.create(candidate: @candidate, ip_address: request.remote_ip) ``` 也能從候選人角度新增一筆資料庫 > 這一行也包括了新增、儲存功能,可將原本那2行刪除 @candidate.votes = @candidate.votes + 1 > @candidate.save > ```ruby= @candidate.vote_logs.create(ip_address: request.remote_ip) ``` ### 在Model(候選人角度) 若Controller使用候選人角度,必須建立新寫的vote_logs方法。 在models/candidate.rb 必須手動建立關係。 ```ruby= has_many :vote_logs ``` ### 在View 顯示票數。 可在rails c 裡面調出VoteLog詳細資料。 ```ruby= <%= candidate.votes %> ``` ## 以Counter Cache計算票數(混亂 先別管) 先修教材「純手工」最後2集 ### 在migration 新增vote_log_count欄位,讓表單vote_logs的結果回到 表單candidtes裡面。 1. 新增/刪除/修改資料表時,要針對magration。因此在終端機新增一個: ```ruby= $rails g migration add_counter_cache_to_candidate ``` 2. 在新增的db/migrate檔案內,在def change內新增add_column方法(表單名, 欄位名, 型態, 其他預設值等) ```ruby= add_column :candidates, :vote_logs, :integer, default: 0 ``` 有migtation就要具現化。若成功,可在schema內看到。 ```ruby= $rails db:migrate ``` 在vote_logs的model檔內加寫 counter_cache:true,令票數寫入時同時更新票數到migration的新欄位。 ```ruby= belongs_to :candidate, counter_cache:true ``` ###### tags: `Rails`