--- title: 12th 鐵人賽 Day_10 問題中場休息-部落格的管理員系統 tags: 12th 鐵人賽 --- # 12th 鐵人賽 Day_10 問題中場休息-部落格的管理員系統 嗨!各位朋友大家好,打給後,歹嘎吼,胎尬喉,我是阿圓,一樣有請今天的one piece: ![](https://i.imgur.com/TxyQvDg.jpg) 居然已經邁入第十天,我的挑戰也已經過了三分之一了,但我居然一行code都沒有放上來!!!這真的太母湯了!趕快來補救一下!那由於今天會放上我的部落格的程式碼,所以字數有點過長,問題就讓我放到明天來寫吧(所以明天會有兩個問題!) ## 定義路徑 ```ruby= # /routes.rb Rails.application.routes.draw do # 這邊為了測試,放了一個index給他,之後想要改成文章的首頁 root 'admins#index' # 我不想要有預設的路徑,直接用最簡單的方式寫給他 get 'admins/sign_in', to: 'admins#sign_in' post 'admins/sign_in', to: 'admins#login' delete 'admins/sign_out', to: 'admins#sign_out' end ``` ## 建立views ```htmlmixed= <!-- admins/views/index.html.erb --> <h1>臨時首頁</h1> <%= link_to '登入', admins_sign_in_path%> <%= link_to '登出', admins_sign_out_path, method: "delete"%> ``` ```htmlmixed= <!-- admins/views/sign_in.html.erb --> <h1>管理者登入</h1> <%= form_for(@admin, url: admins_sign_in_path) do |f| %> <div class="fields"> <%= f.label :account %> <%= f.text_field :account, placeholder:'請輸入帳號' %> </div> <div class="fields"> <%= f.label :password, placeholder:'請輸入密碼' %> <%= f.password_field :password %> </div> <%= f.submit "登入"%> <% end %> ``` ## 建立controller `$ rails g controller admins` 接著定義action,將routes上的action寫上去,至於預設的路徑,就先不處理,之後有需要再來改。 ```ruby= def sign_in #do something end def login #do something end def sign_out #do something end ``` ## 建立model 先建立model `$ rails g model Admin account password:password` Admin有兩個欄位,account 跟 password ```ruby= # /admin.rb class Admin < ApplicationRecord # account password 必填 validates :account, presence: true, uniqueness: true validates :password, presence: true # 在create之前,將密碼加密 before_create :encrypt_password end ``` 自定義自己的密碼加密方式,要在Admin這邊的一個物件create之前將密碼加密,在下面 private 的寫下: ```ruby= private def encrypt_password self.password = popper(password) end def popper(string) string = 'cu' + string + 'te' Digest::SHA1.hexdigest(string) end ``` 所謂 `popper` ,就是在密碼前後加些綴字,讓密碼更難破解(不過我都放上來了XD,就相當於無效了哈哈)。 ## 更改controller裡的action ### sign_in ```ruby= # /admins_controller.rb # 在Admin的類別中,新增一個@admin的實體變數 def sign_in @admin = Admin.new end ``` 現在就有畫面了: ![](https://i.imgur.com/ctsshJt.png) ### login 接著來定義,按下登入按鈕後,要進行的事情: ```ruby= # /admins_controller.rb def login admin = Admin.login(admin_params) # 確認資料庫裡是否有使用相同account和password的管理員 if admin sign_in_admin(admin) #定義在下方,發session redirect_to root_path, notice: '成功登入!' else redirect_to sign_in_admins_path, notice: '請輸入正確帳號密碼' end end ``` 其中,第2行的 `login` 是為了要去比對資料庫裡是否有相同帳號密碼的使用者,所以將方法定義在 admin 的 model 裡面(所有的 admin 都有 login 的方法),如下: ```ruby= # /admin.rb def self.login(options) if options[:account] && options[:password] find_by(account: options[:account], password: Digest::SHA1.hexdigest('cu' + options[:password] + 'te')) end end ``` 上面做了什麼呢?有請圖解! ![](https://i.imgur.com/1vT6j6w.png) 搞定了model的login方法,接著來繼續回來controller,在下面加上: ```ruby= # /admins_controller.rb private def sign_in_admin(a) session[:admin_token] = SecureRandom.uuid # 這裡使用了SecureRandom的方法,他是一個在rails 裡寫好的module,所以要去最上面加上 require 'securerandom' end def admin_params params.require(:admin).permit(:account, :password) end ``` 簡單解釋一下 `admin_params` 做的事情,是將是將登入頁面打過來的資訊,清洗後再傳給 server,若沒有經過 `permit`,在 `create` 資料的時候,就會得到下列畫面: ![](https://i.imgur.com/4pZWyvk.png) 但因為我沒有放東西進去,`login` 這個 `action` 沒有建立新的資料,所以沒有寫,網頁不會噴錯(我把方法改成 `create,`才得到這個畫面!) 這就是所謂的 `Strong parameter`,若想了解其中運作的原理,請參閱[為你自己學 Ruby on Rails](https://railsbook.tw/chapters/13-crud-part-1.html#step06-create-candidate) 。 延續 `login` 的 `action` :若登入成功,就將使用者轉址到根目錄,若失敗重新導入 `sign_in` 的頁面。 ### sign_out 直接把session清掉! ```ruby= # /admins_controller.rb def sign_out sign_out_admin redirect_to root_path, notice: '會員登出成功' end private def sign_out_admin session[:admin_token] = nil end ``` 目前這就是我實作管理員系統的流程,感謝各位看到這邊,若有任何建議,==我非常需要各位的指教==!謝謝大家!我們明天見! ![](https://i.imgur.com/PPbpd2b.gif)