如何创建新的子对象,然后以相同的形式创建与该子对象的has_and_belongs_to_many关系

时间:2015-05-06 22:09:36

标签: ruby-on-rails forms ruby-on-rails-4 has-and-belongs-to-many belongs-to

我是rails和构建关系数据库应用程序的新手。

我有一个有点复杂的数据库结构,我正在尝试创建一个创建子对象的嵌套表单,然后通过habtm关系将该子对象与现有对象相关联。

我的目标是尽可能精简地将数据输入此数据库。我使用Railscast#196-197来实现这一目标。

部分数据库结构:

类别< - habtm - >服务< - belongs_to - >提供者

类别有很多服务,服务可能有很多类别。

提供商拥有许多服务,服务属于单一提供商。

提供商可能拥有许多不同类别的服务。

模特:

class Provider < ActiveRecord::Base
has_many :services, :dependent => :destroy
accepts_nested_attributes_for :services, allow_destroy: true
end

class Service < ActiveRecord::Base
belongs_to :provider
has_and_belongs_to_many :categories
has_many :comments
end

我有一个嵌套表单,允许我从添加提供程序的同一表单中添加服务。

我还生成了一个类别列表(复选框),以允许用户将服务与类别相关联。

问题是,当我提交表单时,没有创建services_categories的连接表。

这是我在提交“创建提供商”表单时收到的来自控制台的信息。我可以看到category_ids []的存储位置,但它们不会被传递到任何地方,并且它们不会在连接表中启动条目的创建。

控制台打印输出:

Started POST "/providers" for ::1 at 2015-05-06 14:38:36 -0700
Processing by ProvidersController#create as HTML
  Parameters: {"utf8"=>"√", "authenticity_token"=>"MJXUbLeh+pT3OSC6B2pfGnsUOBkG1
jim2GUpKD9KC72vp3trLAc4Zf+ICZ6yGLiagTGQXMsJ/j8iDpbpCBhUxQ==", "provider"=>{"name
"=>".Test Provider", "organization"=>".Test Organization", "contact"=>"", "phone
"=>"", "website"=>"", "address1"=>"", "address2"=>"", "city"=>"", "state"=>"Onli
ne", "zip"=>"", "services_attributes"=>{"0"=>{"title"=>".Test Service", "descrip
tion"=>"", "_destroy"=>"0"}}}, "category"=>{"service_ids"=>[""]}, "service"=>{"c
ategory_ids"=>["4", "37", "36"]}, "commit"=>"Create Provider"}
   (0.0ms)  begin transaction
  SQL (2.0ms)  INSERT INTO "providers" ("name", "organization", "address1", "add
ress2", "city", "state", "phone", "website", "contact", "created_at", "updated_a
t") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["name", ".Test Provider"], ["org
anization", ".Test Organization"], ["address1", ""], ["address2", ""], ["city",
""], ["state", "Online"], ["phone", ""], ["website", ""], ["contact", ""], ["cre
ated_at", "2015-05-06 21:38:36.715129"], ["updated_at", "2015-05-06 21:38:36.715
129"]]
  SQL (0.0ms)  INSERT INTO "services" ("title", "description", "provider_id", "c
reated_at", "updated_at") VALUES (?, ?, ?, ?, ?)  [["title", ".Test Service"], [
"description", ""], ["provider_id", 56], ["created_at", "2015-05-06 21:38:36.731
130"], ["updated_at", "2015-05-06 21:38:36.731130"]]
   (39.0ms)  commit transaction
Redirected to http://localhost:3000/providers/56
Completed 302 Found in 84ms (ActiveRecord: 41.0ms)

我的providers_controller.rb(已取出一些不相关的部分):

      class ProvidersController < ApplicationController
### 
    def new 
        @provider = Provider.new        
        @provider.services.build
        @services = Service.all
        @service = Service.new
    end 

    def edit 
        @provider = Provider.find(params[:id])
    end

    def create 
        @provider = Provider.new(provider_params)

        if @provider.save 
            redirect_to @provider
        else 
            render 'new' 
        end 
    end

    ###

    def get_all_categories 
        @categories = Category.find(:all, :order => 'name')
    end 

    private 
        def provider_params 
            params.require(:provider).permit(:name, :organization, :address1, :address2, :city, :state, :zip, :phone, :website, :contact, :service_ids => [], services_attributes: [:id, :title, :description, :_destroy, :category_ids => []])
        end 

end

如您所见,属性:category_ids =&gt; []未显示在控制台的服务属性列表中。

我用于提交提供商数据的表单的相关部分:

<%= form_for @provider do |f| %> 


<%= f.fields_for :services do |builder| %> 

    <%= render "services_fields", :f => builder %>

<% end %>

<%= f.submit %> 

添加新服务的部分格式:

    <%= f.label :title, "Service Title" %><br/> 
<%= f.text_field :title %> <br/>            

<%= f.label :description, "Service Description" %><br/> 
<%= f.text_area :description, :rows => 3 %> <br/>

<p> 
    <label>Associated Categories</label>

<p> 
    <label>Associated Categories</label>
    <div>
        <%= hidden_field_tag "category[service_ids][]", nil %>
        <% Category.all.sort_by{|category| category.name}.each do |category| %>     
            <%= check_box_tag "service[category_ids][]", category.id, 
            @service.categories.include?(category), id: dom_id(category) %>
            <%= label_tag dom_id(category), category.name %></br>
    </div>
        <% end %> 
</p>


<%= f.check_box :_destroy %> 
<%= f.label :_destroy, "Remove Service" %><br/>

我对你能想到的任何方式感兴趣

  • 添加提供商
  • 添加服务
  • 关联服务和类别

所有形式。

我想过有一个弹出窗口可以将用户带到原始的Add Service表单,该表单关联了Categories,但我是Rails的新手,我不知道会有多难。 我也觉得我应该能够在一个页面上完成所有这些工作。

我非常关注服务和类别之间的关系。它适用于应用程序的所有其他部分。

如果我可以发布任何其他相关的代码段,请告诉我。 谢谢!

1 个答案:

答案 0 :(得分:0)

属性:category_ids =&gt; []并未显示在控制台中的服务属性列表中,因为params["provider"]["service_attributes"],它位于params["service"]内部params["provider"]["service_attributes"] 1}}。

这意味着创建操作无法访问category_ids。

如果要在不修改表单的情况下关联创建的服务和类别,可以尝试引用新创建的服务,然后使用&#39; params [&#34; service&#34;]&#39;更新其category_ids。 ,或者在创建提供者之前将category_id添加到params["provider"]["service_attributes"]["category_ids"] = params["service"]["category_ids"] 中:

{{1}}

虽然这需要您将params中允许的属性重新列入白名单。

或者您可以修改表单,以便category_ids最终嵌套在params哈希中的service_attributes中。