簡體   English   中英

在Rails 4控制器中獲取關聯對象的正確方法

[英]Correct way to get an associated object in a Rails 4 controller

這可能是一個重復的問題,因為它似乎非常基礎,但是我一定不能尋找正確的方法。 如您所見,我是Rails的新手。

在Rails 4中,我有兩個對象:“文本”和“項目”。 文本belongs_to :project和Project has_many :texts

創建新文本時,用戶必須從現有項目的下拉菜單中選擇一個項目-他們永遠不會通過文本控制器創建新項目。

因此,我:project' in texts_controller.rb`中將: :project' in列入了白名單:

def text_params

  params.require(:text).permit(:type, :sort_title, :date_created, :project,
  ...

但是現在create方法必須要做:

def create
  @text = Text.new(text_params.except('project'))
  @text.project = Project.find(text_params['project'])
...

為了避免Project(...) expected, got String(...) 顯然,我可以重命名該參數,但是我的表單代碼如下所示:

<p>Select Project</p>
<%= f.collection_select :project, Project.all, :pid, :display_label  %> 

而且我一直無法弄清楚如何在此處更改參數名稱。

我可能完全錯了,實際上是在做正確的事,但是我真的對此表示懷疑。 對於Rails來說,這對我來說不是很習慣,也就是說,我實際上並沒有傳遞項目,而只是傳遞它的id ,盡管以很小的方式,但我覺得我正在打破“ Skinny Controller,Fat Model”的口號。 可能還有其他問題。 什么是正確的“鐵路方式”? TIA!

編輯也許是我的測試很糟糕。 這是我用來測試的工廠:

require 'faker'

FactoryGirl.define do

  factory :text do |t| 
    t.project { FactoryGirl.create(:project) } # not sure if this is right...

    # TODO: creator and contributor, and then catch validation errors in tests
    t.abstract { Array.new(rand(0..2)) { Faker::Lorem.paragraph(rand(1..7)) } }
    t.alternative_title { Array.new(rand(0..5)) { Faker::Lorem.sentence(5,true,3) } }
    t.audience { Array.new(rand(0..2)) { Faker::Lorem.sentence(5,true,3) } }
    t.citation { Array.new(rand(0..2)) { Faker::Lorem.sentence(5,true,3) } }
    t.date_created { rand(900..2000) }
    t.description { Array.new(rand(0..10)) { Faker::Lorem.paragraph(1,true,3) } }
    t.extent { Array.new(rand(0..2)) { Faker::Lorem.sentence(5,true,3) } }
    t.has_part { Array.new(rand(0..20)) { Faker::Lorem.sentence(3,true,5) } }
    t.language { Array.new(rand(0..5)) { Faker::Lorem.sentence(1,false,3) } }
    t.provenance { Array.new(rand(0..2)) { Faker::Lorem.paragraph(rand(1..7)) } }
    t.publisher { Array.new(rand(0..2)) { Faker::Lorem.sentence(3,true,3) } }
    t.rights { Array.new(rand(0..4)) { Faker::Lorem.sentence(5,true,3) } }
    t.series { Array.new(rand(0..2)) { Faker::Lorem.sentence(3,true,5) } }
    t.sort_title { Faker::Lorem.sentence(2,true,5) }
    t.subject { Array.new(rand(0..7)) { Faker::Lorem.sentence(1,true,3) } }
    t.title { Array.new(rand(1..2)) { Faker::Lorem.sentence(3,true,5) } }
    t.toc { Array.new(rand(0..2)) { Faker::Lorem.sentence(5,true,3) } }
    t.type "Text"
  end

end

並且所有POST測試都失敗了: https : //github.com/pulibrary/pul-store/blob/development/spec/controllers/texts_controller_spec.rb#L46-L82

我假設項目已經存在,並且用戶只是從集合下拉列表中選擇它們。

將您的強參數方法更改為:

def text_params
  params.require(:text).permit(:type, :sort_title, :date_created, :project_id,
  ...

然后您的集合選擇字段名稱為:

<p>Select Project</p>
<%= f.collection_select :project_id, Project.all, :pid, :display_label  %> 

最后,將您的控制器操作更改為:

def create
  @text = Text.new(text_params)
  ...

由於Text屬於項目,因此它將具有project_id屬性,您可以直接從參數中分配該屬性,分配該屬性后,它將能夠立即獲取該關聯:

@text = Text.new project_id: 1
@text.project # => #<Project id: 1>

希望能有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM