我有一个Trial模型,该模型在创建时创建treatment_selection和重复。
我想通过重复来保存我试图通过:through关联进行的trial_id和treatment_selection_id。
提交试用表格时,出现以下错误:
undefined method `repetitions' for #<TreatmentSelection:0x007ff76b8c3830>
试用版控制器
def create
@trial = Trial.new(trial_params)
@trial.treatment_selections.build.repetitions.build
end
private
def trial_params
params.require(:trial).permit(:year, :cultivation_id, :region_id, :cooperator_id, :field_id, :property_id, treatment_selections_attributes: [TreatmentSelection.attribute_names.map(&:to_sym).push(:_destroy), repetitions_attributes: [:trial_id, :treatment_selection_id]])
end
模型
class Trial < ApplicationRecord
has_many :treatment_selections, dependent: :destroy
has_many :repetitions, through: :treatment_selections, source: :treatment
accepts_nested_attributes_for :repetitions, allow_destroy: true
accepts_nested_attributes_for :treatment_selections, allow_destroy: true
end
class TreatmentSelection < ApplicationRecord
belongs_to :trial
belongs_to :treatment
end
class Repetition < ApplicationRecord
belongs_to :treatment_selection
end
treatment_selection模型具有以下帮助器,用户可以动态添加该帮助器。 trials_helper
module TrialsHelper
def link_to_add_row(name, f, association, **args)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize, f: builder)
end
link_to(name, '#', class: "add_fields " + args[:class], data: {id: id, fields: fields.gsub("\n", "")})
end
end
架构
create_table "repetitions", force: :cascade do |t|
t.integer "trial_id"
t.integer "treatment_selection_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
登录
Started POST "/trials" for 127.0.0.1 at 2018-10-22 14:45:57 +1000
Processing by TrialsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"I2QheHAPOuhnv61Ghs0UoVgXcbYvX73AA7+nI/JTvRU4lTRYJbOdCstuTt/i7/4H2dV6wv4Vdt6zcQ7oo1id6w==", "trial"=>{"year(2i)"=>"1", "year(3i)"=>"1", "year(1i)"=>"2018", "region_id"=>"3", "cooperator_id"=>"1", "property_id"=>"1", "field_id"=>"5", "cultivation_id"=>"1", "treatment_selections_attributes"=>{"0"=>{"treatment_id"=>"3", "ambassador"=>"0", "_destroy"=>"false"}, "1"=>{"treatment_id"=>"", "ambassador"=>"0", "_destroy"=>"false"}, "2"=>{"treatment_id"=>"", "ambassador"=>"0", "_destroy"=>"false"}}}, "commit"=>"Submit"}
Completed 500 Internal Server Error in 65ms (ActiveRecord: 11.6ms)
NoMethodError (undefined method `repetitions' for #<TreatmentSelection:0x007ff76b8c3830>):
app/controllers/trials_controller.rb:48:in `block in create'
app/controllers/trials_controller.rb:47:in `times'
app/controllers/trials_controller.rb:47:in `create'
试用表格
<%= form_with(model: trial, local: true) do |f| %>
<%= f.date_select :year, {order: [:year] %>
... Other Trial fields...
<%= f.fields_for :treatment_selections do |builder| %>
<%= render 'treatment_selection', f: builder %>
<% end %>
<%= f.submit 'Submit' %>
<% end %>
部分治疗选择
<%= f.collection_select :treatment_id, Treatment.order('name'), :id, :name %>
<%= f.check_box :ambassador %>
<%= f.hidden_field :_destroy, as: :hidden %>
<%= link_to 'Delete', '#', class: "remove_treatment" %>
答案 0 :(得分:2)
您在create
操作@trial.treatment_selections.build
中的代码将返回一个TreatmentSelection
对象,该对象没有模型中定义的repetitions
的定义。
也许你是说:
@trial.treatment_selections.build
@trial.repetitions.build
答案 1 :(得分:1)
您的关联不太正确。
要加入Trial to Repetition,您需要在TreatmentSelection中设置关联以进行以下操作:
class TreatmentSelection < ApplicationRecord
belongs_to :trial
belongs_to :treatment
has_many :repetitions, dependent: :destroy
end
这可以让您正确地进行此关联:
class Trial < ApplicationRecord
has_many :treatment_selections, dependent: :destroy
has_many :repetitions, through: :treatment_selections
end
您还错误地使用了source
选项。当必须告诉ActiveRecord联接模型上哪个关联与所需模型相对应时(名称不匹配时),将使用它。
您还应该删除repetions.trial_id
列,因为它会造成不必要的重复。
您还需要将关联添加到上链的重复项中:
class Repetition < ApplicationRecord
belongs_to :treatment_selection
has_one :treatment, through: :treatment_selection
has_one :trial, through: :treatment_selection
end
您还应该按照以下步骤设置嵌套属性:
class Trial < ApplicationRecord
# ...
accepts_nested_attributes_for :treatment_selections, allow_destroy: true
end
class TreatmentSelection < ApplicationRecord
# ...
accepts_nested_attributes_for :repetitions, allow_destroy: true
end
这很关键,因为属性应该嵌套两个级别。
{
trial: {
treatment_selection_attributes: [
{
treatment_id: 1,
repetition_attributes: [
{ foo: 'bar' }
]
},
{
treatment_id: 1,
repetition_attributes: [
{ foo: 'bar' }
]
}
]
}
}
ActiveRecord无法理解嵌套属性是否经过另一个关联。
您还应该嵌套对fields_for的调用。
<%= form_with(model: trial, local: true) do |f| %>
<%= f.fields_for :treatment_selections do |tsf| %>
<%= tsf.fields_for :repetitions do |rf| %>
<% end %>
<% end %>
<% end %>
答案 2 :(得分:0)
您要在TreatmentSelection模型上构建重复对象,该对象未指定TreatmentSelection和Repetition模型之间的关系, 您需要在TreatmentSelection模型中添加has_many:repetitions才能使其正常工作。