2014-08-29 77 views
0

我試圖創建一個已知的,父產品類型產品的基礎上,這樣的回答: 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

回答

0

爲了解決這個問題,我不得不重構代碼。重構的新方法:

<%= 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表單元素。