如何在a上保存嵌套属性有很多关系

时间:2016-07-08 08:21:39

标签: ruby-on-rails ruby-on-rails-4 ruby-on-rails-5

我遇到了一些问题,我对保存嵌套属性的正确方法感到困惑。

我有两个模型,位置和产品以及一个名为stock的连接表,可以连接这两个模型。

class Location < ApplicationRecord
  has_many :stocks
  has_many :products, :through => :stocks
end

class Product < ApplicationRecord
  has_many :stocks
  has_many :locations, :through => :stocks

  accepts_nested_attributes_for :locations
end

class Stock < ApplicationRecord
  belongs_to :location
  belongs_to :product
end

在我的控制器中我有以下

class ProductsController < ApplicationController
  def index
    @products = Product.all
  end

  def new
    @product = Product.new
    @product.stocks.build
    @locations = Location.all
  end

  def create
    @product = Product.new(product_params)
    if @product.save
      flash[:notice] = "Successfully saved..."
      redirect_to products_path
    else
      flash[:alert] = "Something went wrong, please check the values you entered"
      redirect_to :back
    end
  end

但是我认为我怎么做错了,因为没有任何反应。我想要的是在创建产品时,显示所有可能的位置,以便用户可以选择在哪个位置说明该产品应该存在。当然,这是由股票模型跟踪的。

是谁都在乎开导我?

编辑:我对此进行了一些更改,

我的新观点

<div class="input-field">
  <%= f.label :product_name %>
  <%= f.text_field :name, autofocus: true %>
</div>

<div class="input-field">
  <%= f.label :price %>
  <%= f.text_field :price, autofocus: true %>
</div>


<%= f.fields_for :stocks do |ff| %>
  <div class="input-field">
    <%= ff.collection_select :location_id, Location.all, :id, :structured_location , {:prompt => "Please Select Locations for Product"}, {multiple: true} %>
    <%= ff.label :locations %>
  </div>
<% end %>


<div class="row margin-top x-4">
  <div class="col s12 center-align">
    <%= f.submit "Update", class: "btn wave-effect pink darken-1 btn-large" %>
  </div>
</div>

在product.rb模型中

class Product < ApplicationRecord
  has_many :stocks
  has_many :locations, :through => :stocks

  accepts_nested_attributes_for :stocks

end

现在我可以选择位置,但是当我推送到产品控制器时,我得到了location_id是不允许的

这是我强大的参数

def product_params
    params.require(:product).permit( :name,:price, {stocks_attributes: [:location_id]} )
  end

以下是在控制台中发送的参数

Parameters: {"utf8"=>"✓", "authenticity_token"=>"751Z5I5nBwmYJwFeiXO3jyBnPxqr3Pdz0ohDpN96F0ybE9V4yeUgjt2QYDYZfNvWG4CAdhvGaxIaCmqD6Ka8qw==", "product"=>{"name"=>"Tires Cleaner", "price"=>"4", "stocks_attributes"=>{"0"=>{"location_id"=>["", "1"]}}}, "commit"=>"Update"}

3 个答案:

答案 0 :(得分:1)

由于它是一个很好的关系,你需要告诉强大的参数,它是你发送的数组,然后是特定于位置的属性。此外,所以当你稍后编辑它时,我也会允许:id字段:

params.require(:product).permit(:name, :price, stocks_attributes: [:id, location_id: []]) 

这将允许您发布一系列场地,然后当您编写更新操作后,您还可以编辑场地(不允许:id,它将复制该行)。

答案 1 :(得分:0)

我认为问题在于您需要在产品参数中嵌套位置关系的属性,例如:

params.require(:product).permit(:name, :price, {stocks_attributes: [:id, :location_id]})

答案 2 :(得分:0)

如果位置和产品之间的关系是直接的,那就更容易了。我没有看到股票模型的重要性。一个地方有很多产品,产品有很多地方。因此,

class Location < ApplicationRecord
  has_and_belongs_to_many :products
end

class Product < ApplicationRecord
  has_and_belongs_to_many :locations
end

您需要迁移才能创建库存表。那么你的嵌套表格应该是`

<%= f.fields_for :locations do |ff| %>
  <div class="input-field">
    <%= ff.collection_select :id, Location.all, :id, :structured_location , {:prompt => "Please Select Locations for Product"}, {multiple: true} %>
<%= ff.label :locations %>
  </div>
<% end %>`

我希望它有所帮助。

`