【问题标题】:Nested model form not submitting everything嵌套模型表单未提交所有内容
【发布时间】:2011-11-22 18:12:01
【问题描述】:

我在听 Hypercritical 时听说了这个社区,我很高兴能加入我的第一个问题。我正在开发我的第一个 Rails 应用程序,但遇到了一个似乎无法解决的问题。我已经看 Railscast、Lynda.com 和谷歌搜索好几天了,但我仍然无法理解如何创建一个可以立即更新我的 has_many :through 关联的表单。请允许我尝试解释一下我在做什么。

我的目标: 我工作的公司提供了许多“服务产品”,我希望能够在一个页面上创建一个新的服务产品,并让它创建与之关联的联系人和其他信息。诸如“联系人”之类的附加信息将存在于它们自己的表中,因为它们可能需要被许多“服务产品”引用。

问题: 当我提交表单时,“服务产品”字段提交并输入到数据库中,但“业务开发人员”的字段没有。显然,我希望将所有内容输入到相应的表中,并将 ID 链接到连接表中。我非常感谢您提供的任何见解。

到目前为止我所拥有的:您在下面看到的是服务产品和业务开发人员。最终我会添加联系人、照片和文件,但我认为我会简单地开始并逐步提高。

型号:

class ServiceOffering < ActiveRecord::Base
 attr_accessible :name, :description
 has_many :business_developer_service_offerings
 has_many :business_developers, :through => :business_developer_service_offerings
 accepts_nested_attributes_for :business_developer_service_offerings
end

class BusinessDeveloper < ActiveRecord::Base
 attr_accessible :first_name, :last_name
 has_many :business_developer_service_offerings
 has_many :service_offerings, :through => :business_developer_service_offerings
end

class BusinessDeveloperServiceOffering < ActiveRecord::Base
 belongs_to :business_developer
 belongs_to :service_offering
end

控制器:

def new
 @service_offering = ServiceOffering.new
 @service_offering.business_developers.build
end

def create
 @service_offering = ServiceOffering.new(params[:service_offering])
 if @service_offering.save
  redirect_to(:action => 'list')
 else
  render('new')
 end
end

查看:

<%= form_for((@service_offering), :url => {:action => 'create'}) do |f|%>
    <p>
    <%= f.label :name%>             
    <%= f.text_field :name %>

    <%= f.label :description%>  
    <%= f.text_field :description %>
    </p>

<%= f.fields_for :business_developer do |builder| %>
    <p>
    <%= builder.label :first_name%>
    <%= builder.text_field :first_name %>

    <%= builder.label :last_name%>
    <%= builder.text_field :last_name %>
    </p>
<%end%>
    <%= f.submit "Submit" %>
<%end%>

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 nested-forms nested-attributes


    【解决方案1】:

    我想通了。事实证明,除了@Delba 提出的两个建议之外,还有一些地方是错误的,需要进行更改。

    表格:

    我再次查看RailsCasts #196,发现我的表单看起来与那里使用的不同,所以我尝试匹配它:

        <%= form_for @service_offering do |f|%>
         <p>
          <%= f.label :name%>             
          <%= f.text_field :name %>
    
          <%= f.label :description %>  
          <%= f.text_field :description %>
         </p>
        <%= f.fields_for :business_developers do |builder| %>
         <p>
          <%= builder.label :first_name %>
          <%= builder.text_field :first_name %>
    
          <%= builder.label :last_name %>
          <%= builder.text_field :last_name %>
         </p>
    <%end%>
        <%= f.submit "Submit" %>
    <%end%>
    

    最初,这出现了一个错误:

    undefined method `service_offerings_path'
    

    路线:

    这让我了解了RESTful Routes,因为我使用的是旧的路由样式:

    match ':controller(/:action(/:id(.:format)))'
    

    所以我将路由更新为新的 RESTful Routes 样式:

      get "service_offerings/list"
      resource :service_offerings
      resource :business_developers
    

    attr_accessible

    这使表单可见,但仍然无法正常工作。所以我在这个网站上进行了一些搜索,发现this post 谈到了在 attr_accessible 下将“something_attributes”添加到您的父对象模型。所以我做了:

    class ServiceOffering < ActiveRecord::Base 
     has_many :business_developer_service_offerings
     has_many :business_developers, :through => :business_developer_service_offerings
     accepts_nested_attributes_for :business_developers
     attr_accessible :name, :description, :business_developers_attributes  
    end
    

    上述模型和控制器中显示的@Delba 建议的更改解决了它。

    def new
     @service_offering = ServiceOffering.new
     @business_developer = @service_offering.business_developers.build
    end 
    

    【讨论】:

    【解决方案2】:

    您只是忘记分配@business_developper。

    def new
      @service_offering = ServiceOffering.new
      @business_developper = @service_offering.business_developpers.build
    end
    

    -

    @business_developer = @service_offering.business_developers.build
    

    初始化 biz_dev 的实例,然后在视图中可用。 fields_for :biz_dev 并不真正与此实例相关,而是与 serv_off 和 biz_dev 的多对多关系相关。

    这样,如果您在控制器中初始化另一个 biz_dev 实例,您可以为其他 biz_dev 添加多个输入。例如:

    5.times { @service_offering.biz_dev.build }
    

    将在您的表单中添加其他字段,而无需您在视图中声明它们。

    希望对你有帮助。

    【讨论】:

    • 嗨@Delba。谢谢您的答复。我做了你建议的改变,它有点工作一次,但业务开发人员的值是 NULL。奇怪的是,现在它甚至没有创建业务开发人员,而且和以前一样。控制台显示“警告:无法批量分配受保护的属性:business_developer”。我认为这与 attr_accessible 有关,但我不确定是什么。你有什么想法吗?
    • 我的错。我没有看太深你的代码。写 accept_nested_attributes_for :business_developers(而不是 :business_developer_service_offerings)。保持联系
    • 我解释了我在下面的答案中找到的解决方案。但是,您能否解释一下视图中如何使用“@business_developer = @service_offering.business_developers.build”中的“@business_developer”?是否与“fields_for”中的“:business_developer”相同?如果是这样,为什么“@business_developer”而不是“:business_developer”在视图中不起作用?谢谢!
    • 谢谢@Delba。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-16
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    • 2018-09-03
    相关资源
    最近更新 更多