2015年3月12日 星期四

Ruby on Rails 手工打造新增&顯示頁面

開始自己使用MVC架構手動打造一個網頁,不透過程式自動產生頁面

第一步先新增一個新的專案
rails new my_library
然後將目錄切換到my_library專案之下

routes.rb指定使用者進入某個網頁時的要對應到哪個controller
root 'static_pages#index'
代表連到網頁時要將使用者導向static_pages controller的index
若有寫controller,但在routes中沒有指定,那麼使用者還是連不到

routes中指定了static_pages controller,但我們還尚未新增這個controller
在終端機下打 rails g controller static_pages
就會產生static_pages的controller
這時我們先預覽檔案
就會發現瀏覽器跑出一堆錯誤訊息,大意就是在"workspace/my_library/app/views"這個路徑底下找不到相對應的頁面顯示
要怎麼解決?
在該資料夾下新增一個html頁面,並在頁面中隨便打一些文字
(.erb,代表頁面是使用ruby,rail就會將<% %>中的程式碼翻譯)
 在預覽一次頁面就會看見在html檔中的文字
接下來,來透過程式顯示一些資料
先在static_pages controller中先宣告一些資料

在html檔中,透過each迴圈顯示
上面那段程式碼代表將static_pages中index中宣告的books一個一個取出來放到book變數中,在<li></li>中將book變數顯示出來
預覽結果
也可以指定到某個頁面時,要使用哪個controller的action
但這時static_pages中尚未定義aabbcc,所以就會跳出錯誤
突然忘記routes中的頁面和controller的對應又不想開檔案怎麼辦?
在終端機下打rake routes,就會將目前哪個頁面對應哪個controller及action列出

使用resources指定一個新的controller,使用resource,可以自動產生8個網頁動作對應的controller以及方法

這時預覽頁面一樣會跑錯誤,因為我們尚未產生這個controller
在終端機上輸入rails g controller books,產生books的controller

產生了controller之後,在views/books之下再新增一個index.html.erb
先加上新增書本的連結,有3種寫法,如下圖所示
接下來是新增資料表
建資料表前要先建立model,rails g model book
這樣才能產生建立資料表的程式
程式打好後存檔,並在終端機上執行rake db:migrate,這樣就能建立資料表

rake db:migrate:status可查看最近執行過的資料表新增


若要修改某一欄位的名稱,有幾種方法
  1. rake db:rollback 回到上一步
  2. rails g migration change_name_to_title  新增一個資料表新增的程式
第一個方法非常不好,因為有可能回到上一步就是整個資料表全部不見
正常要使用第2個方法,新增一個新的資料表,在新產生的db新增程式中打
rename_column(:books, :title, :name)

存檔後在終端機在執行一次rake db:migrate,就會執行在新的新增資料表程式中的rename_column,使用新的蓋掉舊的資料

接下來要來打造新增資料的頁面
在app/views/books資料夾底下新增new.html.erb
下一步要在new.html中加上表單(form),我們不使用HTML的傳統表單,改使用Ruby的form_for
1.先在controller定義一筆空的資料給@book
2.將空的@book指定給f
3.將label、text_field等表單元素加上
   f.label :title代表這個label與指定為:title的text_field為一組
   f.submit 加上之後,程式就會知道這個按鈕按下去之後要將表單的資料送出
執行後的畫面如下,程式會自動轉成傳統的tag
畫面做好後,就要來寫資料送出後,將資料寫進資料表
新增資料的action對應到的是create,所以在books_controller中再定義一個create
先將新增的資料透過book_params先篩選過後再存進@book,為什麼要多寫一個book_params呢?
這是有關於資安問題,防止駭客透過網址傳遞參數來修改資料表內的值,在book_params中定義了哪些欄位才可以新增進資料表,就是「params.require(:book).permit(:title, :description , :author, :publish_date)」這行,paramas[:book]中存了剛剛新增的資料,例如:{"title"=>"asp.net", "description"=>"learn", "author"=>"mis", "publish_date"=>"2015/03/11"}(想知道params中存的資料是甚麼,可以先將create中的其他程式註解起來,並將render :text => params[:book]這行取消註解,這樣就可看見params中的資料)
將參數清洗過後就可以存檔,存檔後不管成功或失敗都要給使用者回應,成功的話轉址到首頁,失敗的話程式就會回到新增資料的頁面(不是頁面重整,剛剛輸入的值都還在)

新增好資料後,回到首頁,但是首頁還是一片空空,之前只有放上新增書本的連結,要把資料一筆一筆顯示出來,需要透過each迴圈將一筆一筆資料存進變數中,再使用<ul></ul>將資料排列整齊(不用也可以,直接輸出,但是就是會比較醜)
執行畫面(使用<ul>排列)
執行畫面(不使用<ul>)
另一種排列方法是使表格

執行畫面


這樣新增&顯示的畫面都完成了!