轨道4实例变量ID更改后的新散列和之前创建

问题描述:

我试图创建一个已知的,父产品类型产品的基础上,这样的回答: How to create a nested child from parent object in ruby on rails 4轨道4实例变量ID更改后的新散列和之前创建

产品控制器:

... 

def new 
    @product_type = ProductType.find params[:product_type_id] 
    @product = @product_type.products.new 
end 

def create 
    @product_type = ProductType.find params[:product_type_id] 
    @product = @product_type.products.build(product_params) 
    if @product.save 
    flash[:notice] = 'Product created.' 
    redirect_to(:action => 'index') 
    else 
    render("new") 
    end 
end 

新方法的行为如预期。当创建运行时,它获取一个散列:代替product_type_id的整数,如图所示在控制台:

参数:{ “UTF8”=> “✓”, “authenticity_token”=>“dmGMF6uENfUtkwgwI6GrnvBawIFA6M6Z/ELikQn9gGs = “,”product“=>”年份“=>”2015“,”brand_id“=>”9“,”名称“=>”a“,”说明“=>”b“,”thumbnail_desc“=> “,”category_ids“=> [”“,”29“],”product_class_ids“=> [”“],”image_base“=>”“,”media_embed“=>”“,”vendor_sku“=>”“, “msrp”=>“22”,“price_override”=>“”,“visible”=>“1”,“available”=>“1”},“product_type_id”=> {“39”=>“”}} ,“提交”=>“保存”}

因此,查找失败。抛出的错误是未知键:39.

该模型:ProductTypes有很多产品和产品属于ProductTypes。

这是一个来自Rails2的长期逾期重写。在那里,@product_type实例变量从新建立到创建。

谢谢您的考虑和帮助。

这里是产品形式:

<%= form_for([:admin, @product]) do |form| %> 
    <% if @product.errors.any? %> 
    <div id="error_explanation"> 
     <h2><%= pluralize(@product.errors.count, "error") %> prohibited this page from being saved:</h2> 

     <ul> 
     <% @product.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 

<table cellpadding="0" cellspacing="0" class="admintable"> 
    <tr> 
    <th>Year</th> 
    <td><%= form.text_field :year, :size => 5 %></td> 
    </tr> 
    <tr> 
    <th>Brand</th> 
    <td><%= form.select(:brand_id, @brands.map {|b| [b.name, b.id]}) %></td> 
    </tr> 
    <tr> 
    <th>Product Name</th> 
    <td><%= form.text_field :name, :size => 30 %></td> 
    </tr> 
    <tr> 
    <th>Description</th> 
    <td><%= form.text_area :description, :cols => 60, :rows => 30 %></td> 
    </tr> 
    <tr> 
    <th>Thumbnail Description</th> 
    <td><%= form.text_area :thumbnail_desc, :cols => 60, :rows => 5 %></td> 
    </tr> 
    <tr> 
    <th>Categories</th> 
    <td> 
    <%= form.collection_select :category_ids, Category.sorted, :id, :name, {}, {:multiple => true, include_blank: true, :size => 20 } %> 
    </td> 
    </tr> 

    <tr> 
    <th>Product Class</th> 
    <td> 
    <%= form.collection_select :product_class_ids, ProductClass.options_for_select(@product.product_type_id), :id, :name, {}, {:multiple => true, include_blank: true, :size => 4 } %> 
    </td> 
    </tr> 

    <tr> 
    <th>Image Base</th> 
    <td><%= form.text_field :image_base, :size => 40 %></td> 
    </tr> 

    <tr> 
    <th>Media Embed Code</th> 
    <td><%= form.text_area :media_embed, :cols => 60, :rows => 5 %></td> 
    </tr> 

    <tr> 
    <th>Vendor SKU</th> 
    <td><%= form.text_field :vendor_sku, :size => 30 %></td> 
    </tr> 

    <% if @product_type.has_price? -%> 
    <tr> 
    <th>MSRP</th> 
    <td><%= form.text_field :msrp, :size => 5 %></td> 
    </tr> 

    <tr> 
    <th>BW Price</th> 
    <td><%= form.text_field :price_override, :size => 5 %></td> 
    </tr> 
    <% end -%> 

    <tr> 
    <th>Visible?</th> 
    <td><%= form.check_box :visible %></td> 
    </tr> 

    <tr> 
    <th>Available?</th> 
    <td><%= form.check_box :available %></td> 
    </tr> 

    <% unless @product.active -%> 
    <tr> 
    <th>Active</th> 
    <td><%= form.check_box :active %></td> 
    </tr> 
    <% end -%> 

    <%= hidden_field :product_type_id, "#{@product_type.id}" %> 
    <tr> 
    <th>&nbsp;</th> 
    <td><%= form.submit "Save" %></td> 
    </tr> 
</table> 
<% end %> 

产品型号:

class Product < ActiveRecord::Base 

    belongs_to :brand 
    belongs_to :product_type 

    has_and_belongs_to_many :categories 
    has_and_belongs_to_many :colors 
    has_and_belongs_to_many :product_classes 

    validates_presence_of :name, :categories 
    validates_presence_of :msrp, :if => Proc.new { |p| p.price_override != nil } 
    validates_numericality_of :year, :greater_than => 2007, :allow_nil => true 
    validates_numericality_of :msrp, :price_override, :greater_than => 0, :allow_nil => true 

    scope :sorted, lambda { order("name ASC") } 
    scope :notdeleted, lambda { where(:deleted_at => nil) } 

    def display_name(model = nil) 
    str = model ? model.actual_name : name 
    str = "#{brand_year_prefix} #{str}" if product_type.name_has_prefix? 
    str 
    end 

    def brand_year_prefix 
    str = brand.display_name if product_type.name_includes_brand 
    str = "#{year} #{str}" if product_type.name_includes_year 
    str.strip 
    end 

    def model_name(model, include_brand = false) 
    str = model.actual_name 
    str = "#{brand.display_name} #{str}" if include_brand 
    str = "#{year} #{str}" if product_type.model_name_includes_year 
    str 
    end 

    def price 
    price_override ? price_override : msrp 
    end 

    def onsale 
    price_override ? '<span class="red">Sale: ': '<span class=""> ' 
    end 

    def has_product_pricing? 
    price != nil 
    end 

    def has_one_price? 
    has_product_pricing? && models.all? { |m| !m.has_model_pricing? } 
    end 

    def can_be_purchased? 
    visible? && available? && deleted_at.nil? && (!product_type.has_models || models.any? { |m| m.can_be_purchased? }) 
    end 

    def real_image_path 
    image_base.blank? ? AppConfig.default_product_image : image_base 
    end 

    def thumb_image_path 
    real_image_path + "-t.jpg" 
    end 

    def standard_image_path 
    real_image_path + "-s.jpg" 
    end 

    def large_image_path 
    real_image_path + "-l.jpg" 
    end 

    def active 
    deleted_at.nil? 
    end 

    def active=(val) 
    self.deleted_at = [nil, '', '0', false].member?(val) ? Time.now : nil 
    end 

    def self.compare_year(a, b) 
    a_has_year = !a.year.blank? && a.product_type.name_includes_year? 
    b_has_year = !b.year.blank? && b.product_type.name_includes_year? 
    return 0 if !a_has_year && !b_has_year 
    return -1 if a_has_year && !b_has_year 
    return 1 if b_has_year && !a_has_year 
    b.year <=> a.year 
    end 

    def self.compare_brand(a, b) 
    a_has_brand = !a.brand.nil? && a.product_type.name_includes_brand? 
    b_has_brand = !b.brand.nil? && b.product_type.name_includes_brand? 
    return 0 if !a_has_brand && !b_has_brand 
    return -1 if a_has_brand && !b_has_brand 
    return 1 if b_has_brand && !a_has_brand 
    a.brand.display_name <=> b.brand.display_name 
    end 
end 

而且产品类型型号:

class ProductType < ActiveRecord::Base 

    has_many :product_classes 
    has_many :products 

    validates_presence_of :name 

    scope :sorted, lambda { order("name ASC") } 
    scope :notdeleted, lambda { where(:deleted_at => nil) } 

    def active 
    deleted_at.nil? 
    end 

    def active=(val) 
    self.deleted_at = [nil, '', '0', false].member?(val) ? Time.now : nil 
    end 

end 
+0

你可以发布你的产品查看表单和product/productType模型文件。另外,要开始,至少在您发布的链接中它的方式如何,您的方法new中的“@ product”应该是“@product = Product.new”# – jrich 2014-08-29 19:29:28

+0

更改新方法并不会改变结果。当点击保存时,我仍然得到:未知键:39这是实际的product_type_id。 – 2014-08-30 00:10:18

为了解决这个问题,我不得不重构代码。重构的新方法:

<%= form_for([:admin, @product], :url => {:action => 'create', :product_type_id => @product_type.id}) do |form| %> 

<%= render :partial => 'form', :locals => {:form => form} %> 

<div class="form-buttons"> 
    <%= submit_tag("Create #{@product_type.name}") %> 
</div> 

<% end %> 

然后_form.html.erb只有html表单元素。