iT邦幫忙

DAY 18
0

從想法到快速實作的捷徑:Rails系列 第 18

[ Day 18 ][ Dev ] 簡單的Model資料表關聯

  • 分享至 

  • xImage
  •  

在之前的開發中,我們只簡單新建了資料表。

而在rails中,要去跟資料庫拿資料的就是model,

裡面能設定association、validation、callback,以及scope......等等。

今天就用post.rb來介紹一下rails的model。

Association

舉例來說,我們知道每個po文會有作者,

但我們現在作者和po文是分開的,該怎樣把它們連起來呢?

首先先在每一則post裡加上user_id。

概念:因為每一個po文只會屬於一個user。

rails g migration add_user_id_to_posts user_id:integer

加上user_id之後我們讓rails有辦法去找到關聯,

但是我們還沒告訴它如何去找。

所以在以下post以及user的model裡面加上belongs_to、has_many:

class Post < ActiveRecord::Base
  validates :title, presence: true, length: {maximum: 50}

  belongs_to :user
  
end






class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :posts
end

> 這裡的動詞和名詞複數變化,也跟程式無關,只要用一般的英文文法去想就ok了

現在進去rails console裡面,隨便找一個user:

user = User.first

再輸入user.posts就可以找到目前屬於這個user發的po文,

目前會回傳一個空的array,不過我們可以在這裡直接新增一個post,

user.posts.create(title:"Whatever", content:"doesn't matter")

不過這樣手動測並不是一個好方法,rspec也有辦法測model間的association。

在開始之前我們得做一點小小的修正,

因為我們在contoller加上authenticate\_user!這個before_filter,

所以現在運行post\_controller\_spec.rb會出錯,

這裡要在spec_helper.rb裡面require 'devise',

然後加入tests_heler。

config.include Devise::TestHelpers, :type => :controller

接著我們就可以在controller spec裡面去讓假的user登入了。

    let(:user) { Fabricate(:user) }
    before { sign_in user } 

這兩行就可以搞定所有事情。

不過改完會發現仍然有錯誤,問題很簡單,

因為我們還沒在Fabricate裡面新增假造的user。

Fabricator(:user) do
  name { Faker::Name.name }
  email { Faker::Internet.email }
  password { Faker::Internet.password }
end

這樣舊的測試就可以跑起來了,準備開始測post的model。

首先下載一個gem,記得照著readme上面的提醒加上require: false的選項,

不然每個檔案都require這一個gem,可能會發生神奇的錯誤。

(我猜是因為裡面的has\_manybelongs\_to兩個matcher會和原本rails在model中使用的衝突到)

再來記得在rails_helper.rb裡面require進來,

如果是2.x的rspec就放在spec_helper.rb裡面,__否則會出錯__。 Q_Q

再來就是測試的code啦!

看著shoulda文件很清楚,不過這裡還是簡單做一次

require 'rails_helper'

RSpec.describe User, :type => :model do
  let(:user) { Fabricate(:user) } 

  it "should have many posts" do
    expect(user).to have_many(:posts)
  end
end






require 'rails_helper'

RSpec.describe Post, :type => :model do
  let(:post) { Fabricate(:post) } 
  
  it "should belong to user" do
    expect(post).to belong_to(:user)
  end
end

通過之後我們可以在新增文章的地方加入hidden field來設定po文的作者是誰,

也記得加入strong parameter。

  private

  def post_params
    params.require(:post).permit( :user_id,:title, :content, :note, :source)
  end






<%= f.input :user_id, as: :hidden, input_html: { :value => current_user.id} %>

再來就可以在文章列表(post的index頁面)加上欄位啦!

現在看起來醜醜的,而且放太多邏輯在view裡面是不好的行為,

之後會refactor這些東西,今天就先知道這樣就好啦!

參考資料:
https://github.com/thoughtbot/shoulda-matchers


上一篇
[ Day 17 ][ Deploy ] 部署到 heroku
下一篇
[ Day 19 ] 支援多國語系 - i18n
系列文
從想法到快速實作的捷徑:Rails30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言