我的rails应用程序中有以下模型:
class SaleContact < ActiveRecord::Base
validates :key_contact_id, presence: true, uniqueness: { scope: :sales_opportunity_id, message: "Contact already added!" }
validates :sales_opportunity_id, presence: true
belongs_to :key_contact, inverse_of: :sale_contacts
belongs_to :sales_opportunity, inverse_of: :sale_contacts
has_many :phone_numbers, :through => :key_contact
accepts_nested_attributes_for :phone_numbers
end
我正在尝试通过选择key_contact(假设key_contact已存在)从sales_opportunity屏幕创建sale_contact。我还希望能够使用fields_for和嵌套属性同时添加phone_number。
class KeyContact < ActiveRecord::Base
validates :first_name, :last_name, :company_id, presence: true
has_many :phone_numbers, dependent: :destroy
belongs_to :company
has_many :sales_opportunities, :through => :sale_contacts
has_many :sale_contacts, dependent: :destroy
end
假设我已经创建了key_contact并将其分配给拥有它的公司。
class PhoneNumber < ActiveRecord::Base
validates :number, :key_contact_id, presence: true
belongs_to :key_contact
end
这里没什么神奇的 - 只是一个非常基本的电话号码模型。
在sales_opportunity页面上,我可以加载一个添加新sale_contact的模式。它是由AJAX加载的引导模式,但我不认为这很重要(为了简洁,我只包括表单部分):
<%= form_for(@sale_contact, :html => {role: :form, 'data-model' => 'sale_contact'}, remote: true) do |f| %>
<% if @sale_contact.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@sale_contact.errors.count, "error") %> prohibited this sale_contact from being saved:</h2>
<ul>
<% @sale_contact.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group" id= "contact_error">
<%= f.label :key_contact_id, :class => "control-label" %>
<div id="contact_select">
<%= f.collection_select :key_contact_id, @sales_opportunity.company.key_contacts(:full_name), :id, :full_name %>
</div>
<span class="warning-block"></span>
<span class="help-block"></span>
</div>
<div class="form-group">
<%= f.label :role, :class => "control-label" %>
</br>
<%= f.select(:role, options_for_select(@roles.collect { |r| [r[0].humanize, r[0]] }, selected: @sale_contact.role), {}) %>
<span class="help-block"></span>
</div>
<div class="form-group">
<%= f.label :preference, :class => "control-label" %>
</br>
<%= f.select(:preference, options_for_select(@preferences.collect { |r| [r[0].humanize, r[0]] }, selected: @sale_contact.preference), {}) %>
<span class="help-block"></span>
</div>
<%= f.fields_for(:phone_numbers) do |phone| %>
<div class="form-group">
<%= phone.label :number, "Phone Number", :class => "control-label" %>
</br>
<%= phone.text_field :number, :placeholder => "Enter phone number (optional)" %>
<span class="help-block"></span>
</div>
<div>
<%= phone.hidden_field :key_contact_id %>
</div>
<% end %>
<div class="form-group">
<%= f.hidden_field :sales_opportunity_id, :value => @sales_opportunity.id %>
</div>
<%= f.submit "Save", class: "btn btn-large btn-success", data: { disable_with: "Submitting..." }%>
<% end %>
从我的sale_contact_controller新动作:
def new
@sale_contact = SaleContact.new
@sale_contact.phone_numbers.build
@sales_opportunity = SalesOpportunity.find(params[:sales_opportunity_id])
@company = @sales_opportunity.company
@roles = SaleContact.roles
@preferences = SaleContact.preferences
render :modal_form
end
def sale_contact_params
params.require(:sale_contact).permit(:key_contact_id, :sales_opportunity_id, :role, :preference, phone_numbers_attributes: [:number, :id])
end
当通过AJAX检索模态或key_contact选择下拉列表更改以将key_contact_id引入phone_numbers_attributes时,我运行javascript片段;如果我不这样做,我得到422不可处理的实体错误,因为我没有通过我的key_contact_id发送。
使用此设置,模式弹出视图并具有正确的字段(包括sale_contact和phone_number),但不会保存这些模型 - 我收到500错误:
Completed 500 Internal Server Error in 17ms
ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection (Cannot modify association 'SaleContact#phone_numbers' because the source reflection class 'PhoneNumber' is associated to 'KeyContact' via :has_many.):
app/controllers/sale_contacts_controller.rb:50:in `block in create'
app/controllers/sale_contacts_controller.rb:49:in `create'
我尝试过其他方法,例如在sale_contact create方法中设置key_contact_id,但我得到了相同的结果。当我没有传递key_contact_id(422错误)并且在我这样做时抱怨(由于rails关联在内部设置key_contact_id而导致500内部服务器错误)时,我无法理解为什么这个设置会抱怨。
Rails希望我在这做什么?
答案 0 :(得分:1)
我的表单存在类似问题,但我可以使用嵌套的field_for标记传递它
<强> Proposal.rb 强>
has_many :proposal_section_reviews, :through => :proposal_review_status
has_one :proposal_review_status, :dependent => :destroy
attr_accessible :proposal_review_status_attributes, :proposal_review_status_attributes, :proposal_section_reviews_attributes
accepts_nested_attributes_for :proposal_review_status, :proposal_section_reviews
<强> ProposalSectionReview.rb 强>
belongs_to :proposal_review_status
<强> ProposalReviewStatus.rb 强>
has_many :proposal_section_reviews, :dependent => :destroy
<强> _form.html.haml 强>
= form_for proposal do |f|
= f.fields_for :proposal_review_status do |ff|
= ff.fields_for :proposal_section_reviews
所以在你的实例中我会尝试
<%= f.fields_for(:key_contact) do |key| %>
<%= key.fields_for(:phone_numbers) do |phone| %>
<div class="form-group">
<%= phone.label :number, "Phone Number", :class => "control-label" %>
</br>
<%= phone.text_field :number, :placeholder => "Enter phone number (optional)" %>
<span class="help-block"></span>
</div>
<div>
<%= phone.hidden_field :key_contact_id %>
</div>
<% end %>
<% end %>
希望这有帮助