同一模型的不同实例(多个has_many通过关联)

时间:2015-10-05 11:59:02

标签: ruby-on-rails associations

我的项目中有多个has_many关系,并且正在寻找有关如何使用表单更新值的帮助。

有两种基本模式:产品和国家。产品可以来自多个来源国家,并且有多个目的地国家/地区。 (我无法为这个例子提出一个很好的比喻)

create_table "nations", force: :cascade do |t|
  t.string "name"
end

create_table "products", force: :cascade do |t|
  t.string "name"
  t.string "bio"
end

create_table "dest_nation", force: :cascade do |t|
  t.integer "product_id"
  t.integer "nation_id"
end

create_table "orig_nation", force: :cascade do |t|
  t.integer "product_id"
  t.integer "nation_id"
end

然后我创建了如下关系:

class Product < ActiveRecord::Base
  has_many :dest_nations
  has_many :destination, :class_name=> 'nations', through: :dest_nation
  has_many :orig_nations
  has_many :origin, :class_name=> 'nations', through: :orig_nations 
end

class Nation < ActiveRecord::Base
  has_many :dest_nations
  has_many :imports, :class_name => 'products', through: :dest_nation
  has_many :orig_nations
  has_many :exports, :class_name =>'products', through: :orig_nations 
end

class DestNation < ActiveRecord::Base
  belongs_to :nation
  belongs_to :product
end

class OrigNation < ActiveRecord::Base
  belongs_to :nation
  belongs_to :product
end

问题: 1.)当产品注册时,我想知道用户可以从选项列表中选择的源和目的地国家。如何在视图和控制器中进行这些更改以适当地反映这些更改。

<%= form_for @product do |f|%>
  <div class="form-group">
    <%= f.label :name, "Name of the product:"%>
    <%= f.text_field :name, class: "form-control" %>
  </div>
  <div class="form-group">
    <%= f.label :bio, "A brief summary:"%>
    <%= f.text_area :bio, class: "form-control", rows:3%>
  </div>
  <!-- For origination country -->
  <%= f.collection_check_boxes :nation_ids, Nation.all, :id, :name do |cb|%>
    <% cb.label(class: "checkbox-inline input_checkbox") {cb.check_box(class: "checkbox") + cb.text}%>
  <% end %>
  <br>
<!-- For destination country -->
  <%= f.collection_check_boxes :nation_ids, Nation.all, :id, :name do |cb1|%>
    <% cb1.label(class: "checkbox-inline input_checkbox") {cb1.check_box(class: "checkbox") + cb1.text}%>
  <% end %>
  <br>                  
<%= f.submit "Submit", class: "btn btn-default btn-primary" %> 
<%end%>

我的产品控制器

def create
  @product = Product.new(product_params)
  if @product.save
    flash[:success] = ""
    redirect_to root_path
  else
    render 'new'
  end    
  # binding pry
end

def product_params
  params.require(:product).permit(:name,:bio, nation_ids: [])
end

2 个答案:

答案 0 :(得分:0)

  

产品可以来自多个原产国并拥有   多个目的地国家

听起来你正在寻找has_and_belongs_to_many协会:

enter image description here

这将使您的问题更容易处理:

#app/models/product.rb
class Product < ActiveRecord::Base
   has_and_belongs_to_many :destinations,
      :class_name =>"Nation",
      join_table: :destinations,
      foreign_key: :product_id,
      association_foreign_key: :nation_id

   has_and_belongs_to_many :origins, 
      :class_name =>"Nation",
      join_table: :origins,
      foreign_key: :product_id,
      association_foreign_key: :nation_id
end

#app/models/nation.rb
class Nation < ActiveRecord::Base
   has_and_belongs_to_many :exports, 
      :class_name=> "Product",
      join_table: :origins,
      foreign_key: :nation_id,
      association_foreign_key: :product_id

   has_and_belongs_to_many :imports, 
      :class_name=> "Product",
      join_table: :destinations,
      foreign_key: :nation_id,
      association_foreign_key: :product_id
end

您必须使用以下表格备份这些:

create_table "destinations", id: false do |t|
  t.integer "product_id"
  t.integer "nation_id"
end

create_table "origins", id:false do |t|
  t.integer "product_id"
  t.integer "nation_id"
end
  

如何在视图和控制器中进行这些更改   适当反映这些变化

#app/controllers/products_controller.rb
class ProductsController < ApplicationController
   def new
       @product = Product.new
   end

   def create
       @product = Product.new(product_params)
   end

   private

   def product_params
      params.require(:product).permit(:x, :y, :origins, :destinations)
   end
end

#app/views/products/new.html.erb
<%= form_for @product do |f|%>
   <%= f.collection_check_boxes :origins, Nation.all, :id, :name %>
   <%= f.submit %>
<% end %>

答案 1 :(得分:0)

终于找到了解决方案。

仅在此处的答案部分列出编辑

  

模型/ product.rb

class Product < ActiveRecord::Base
  has_many :dest_nations
  has_many :destinations, through: :dest_nations, :source => 'nation'
  has_many :orig_nations
  has_many :origins, through: :orig_nations, :source => 'nation'
end

对nation.rb进行了类似的更改

  

表单摘要读取(new.html.erb)

<%= f.collection_check_boxes :origin_ids, Nation.all, :id, :name do |cb1|%>
<% cb1.label(class: "checkbox-inline input_checkbox") {cb1.check_box(class: "checkbox") + cb1.text}%>
  
  

最后,产品参数更新如下(在products_controller.rb中)

params.require(:product).permit(:name,:bio, origin_ids: [], destination_ids: [])