这可能是一个重复的问题,因为它似乎非常基本,但我不能以正确的方式搜索。正如你所看到的,我是Rails的新手。
在Rails 4中,我有两个对象:Text和Project。文字belongs_to :project
和项目has_many :texts
。
创建新文本时,用户必须从现有项目的下拉列表中选择项目 - 他们永远不会通过文本控制器创建新项目。
所以,我已将:project' in
texts_controller.rb`列入白名单:
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(...)
。显然我可以重命名param,但我的表单代码如下:
<p>Select Project</p>
<%= f.collection_select :project, Project.all, :pid, :display_label %>
我无法弄清楚如何在那里更改参数名称。
我可能完全错了,实际上是做对了,但我真的很怀疑; Rails对我来说感觉不太习惯,即我实际上并没有传递一个项目,只是它的id
,而且,尽管我只是一个小小的方式,我觉得我打破了“瘦控制器,胖模型“口头禅。可能还有其他问题。这样做的“Rails方式”是什么? 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
答案 0 :(得分:1)
我假设项目已经存在且用户只是从集合下拉列表中选择它们。
将您的强参数方法更改为:
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 belongs_to项目,它将具有project_id
属性,您可以直接从params分配,并且一旦分配它就能够获取关联:
@text = Text.new project_id: 1
@text.project # => #<Project id: 1>
希望有所帮助。