【问题标题】:How to create a new child object and then create a has_and_belongs_to_many relationship with that child object in the same form如何创建一个新的子对象,然后以相同的形式与该子对象创建 has_and_belongs_to_many 关系
【发布时间】:2015-05-06 22:09:35
【问题描述】:

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

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

我的目标是尽可能简化将数据输入此数据库的过程。我使用 Railscast #196-197 做到了这一点。

部分数据库结构:

category service provider

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

提供者有许多服务,服务属于单个提供者。

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

型号:

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 =>[] 未显示在控制台的服务属性列表中。

我用来提交提供者数据的表单的相关部分:

<%= 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/>

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

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

都在一种形式中。

我曾想过有一个弹出窗口将用户带到与类别相关联的原始添加服务表单,但我是 Rails 新手,我不知道这会有多困难。 我也觉得我应该能够在一页上完成所有操作。

我非常愿意在服务和类别之间建立一种习惯关系。它适用于应用程序的所有其他部分。

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

【问题讨论】:

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


    【解决方案1】:

    属性 :category_ids =>[] 未显示在控制台的服务属性列表中,因为它不包含在 params["provider"]["service_attributes"], 中,而是在 params["service"] 中。

    这意味着创建操作没有访问 category_ids。

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

    params["provider"]["service_attributes"]["category_ids"] = params["service"]["category_ids"]
    

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

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

    【讨论】:

    • 非常感谢您花时间回答问题。我正在阅读并重新阅读您的答案,并尝试了一些关于如何实施它的想法,但没有任何成功。我将向控制器添加什么来实现,例如:引用新创建的服务,然后使用 'params["service"] 更新其 category_ids
    猜你喜欢
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多