2016-05-05 9 views
1

これは非常に古くなっているので、私はのいずれかをダウンロードすることができないよ、動的なフォーム、NoMethodError

https://github.com/railscasts/403-dynamic-forms

私はレールに新たなんだ、と私はこのrailscastオフに基づいて何かを構築しました。それが信頼できる古い宝石 - 少なくともRVMを使って - 本当にそれを確認することはできません。

しかし、誰かがそれをレール3から4.2、https://github.com/asang/403-dynamic-formsに更新しましたが、私はundefined method 'fields' for nil:NilClassエラーを受けています。それは、コントローラを持っていない場合product_field.rbアクセス:field_type、および:nameを行う方法

Product.rb側の問題では

class Product < ActiveRecord::Base 
    belongs_to :product_type 
    serialize :properties, Hash 

validate :validate_properties 

def validate_properties 
    product_type.fields.each do |field| 
    if field.required? && properties[field.name].blank? 
    errors.add field.name, "must not be blank" 
    end 
    end 
end 
end 

、レール4.2にレール3から変更、 ?

Product_field.rb - レール3

class ProductField < ActiveRecord::Base 
belongs_to :product_type 
attr_accessible :field_type, :name, :required 
end 

Product_field.rb - レール4.2

class ProductField < ActiveRecord::Base 
belongs_to :product_type 
end 

Product_types_controller.rb

class ProductTypesController < ApplicationController 

def index 
    @product_types = ProductType.all 

    respond_to do |format| 
    format.html 
    format.json { render json: @product_types } 
    end 
end 


def show 
    @product_type = ProductType.find(params[:id]) 

    respond_to do |format| 
    format.html 
    format.json { render json: @product_type } 
    end 
end 


def new 
    @product_type = ProductType.new 

    respond_to do |format| 
    format.html 
    format.json { render json: @product_type } 
    end 
    end 

def edit 
    @product_type = ProductType.find(params[:id]) 
end 


def create 
    @product_type = ProductType.new(product_type_params) 

    respond_to do |format| 
    if @product_type.save 
     format.html { redirect_to @product_type, notice: 'Product type was successfully created.' } 
    format.json { render json: @product_type, status: :created, location: @product_type } 
    else 
    format.html { render action: "new" } 
    format.json { render json: @product_type.errors, status: :unprocessable_entity } 
    end 
    end 
    end 


def update 
    @product_type = ProductType.find(params[:id]) 

    respond_to do |format| 
    if @product_type.update_attributes(product_type_params) 
     format.html { redirect_to @product_type, notice: 'Product type was successfully updated.' } 
     format.json { head :no_content } 
    else 
     format.html { render action: "edit" } 
     format.json { render json: @product_type.errors, status: :unprocessable_entity } 
    end 
    end 
end 


def destroy 
    @product_type = ProductType.find(params[:id]) 
    @product_type.destroy 

    respond_to do |format| 
    format.html { redirect_to product_types_url } 
    format.json { head :no_content } 
    end 
end 

def product_type_params 
    params.require(:product_type).permit(
     :name, fields_attributes: [ :field_type, :name, :required ]) 
end 
end 

Product_controller.rb

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

     def show 
     @product = Product.find(params[:id]) 
     end 

     def new 
     @product = Product.new(product_type_id: params[:product_type_id]) 
     end 

     def edit 
     @product = Product.find(params[:id]) 
     end 

     def create 
     @product = Product.new(product_params) 
     if @product.save 
      redirect_to @product, notice: 'Product was successfully created.' 
     else 
      render action: "new" 
     end 
     end 

     def update 
     @product = Product.find(params[:id]) 
     if @product.update_attributes(product_params) 
      redirect_to @product, notice: 'Product was successfully updated.' 
     else 
      render action: "edit" 
     end 
     end 

     def destroy 
     @product = Product.find(params[:id]) 
     @product.destroy 
     redirect_to products_url 
     end 

     private 

     def product_params 
     params.require(:product).permit(:name, :price, :product_type_id, 
            :properties) 
     end 
    end 

_form.html.erb

<%= form_for @product do |f| %> 
     <% if @product.errors.any? %> 
     <div id="error_explanation"> 
      <h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h2> 
      <ul> 
      <% @product.errors.full_messages.each do |msg| %> 
      <li><%= msg %></li> 
      <% end %> 
      </ul> 
     </div> 
     <% end %> 

     <%= f.hidden_field :product_type_id %> 

     <div class="field"> 
     <%= f.label :name %><br /> 
     <%= f.text_field :name %> 
     </div> 
     <div class="field"> 
     <%= f.label :price %><br /> 
     <%= f.text_field :price %> 
     </div> 

     <%= f.fields_for :properties, OpenStruct.new(@product.properties) do |builder| %> 
     <% @product.product_type.fields.each do |field| %> 
      <%= render "products/fields/#{field.field_type}", field: field, f: builder %> 
     <% end %> 
     <% end %> 

     <div class="actions"> 
     <%= f.submit %> 
     </div> 
    <% end %> 

ログイン

Completed 500 Internal Server Error in 9ms (ActiveRecord: 0.0ms) 

    ActionView::Template::Error (undefined method `fields' for nil:NilClass): 
     22: </div> 
     23: 
     24: <%= f.fields_for :properties, OpenStruct.new(@product.properties) do |builder| %> 
     25:  <% @product.product_type.fields.each do |field| %> 
     26:  <%= render "products/fields/#{field.field_type}", field: field, f: builder %> 
     27:  <% end %> 
     28: <% end %> 
     app/views/products/_form.html.erb:25:in `block (2 levels) in _app_views_products__form_html_erb__38604707748806799_70122829936940' 
     app/views/products/_form.html.erb:24:in `block in _app_views_products__form_html_erb__38604707748806799_70122829936940' 
     app/views/products/_form.html.erb:1:in `_app_views_products__form_html_erb__38604707748806799_70122829936940' 
     app/views/products/new.html.erb:3:in `_app_views_products_new_html_erb__487839569246893265_70122829438980' 

その他これと同じ問題を抱えてコメントを投稿railscastに誰か、それはしなければならないと言った<%= f.hidden_field :product_type_id %>私は何かを忘れていますか?これを見越す時間をとってくれてありがとう、おそらく、ばかげた間違い。

答えて

1

問題は、ProductsController#newでこの行に@productをインスタンス化している方法である:

def new 
    @product = Product.new(product_type_id: params[:product_type_id]) 
end 

あなたは、そのIDではなく、具体的な基準として、PRODUCT_TYPEを参照しています。 newのアクションで@productが保存されないため、@product.product_typeはデータベースからロードされず、常にnilになります。修正するには、product_typeをロードし、新しい製品から直接参照してください:

def new 
    product_type = ProductType.find(params[:product_type_id]) 
    @product = Product.new(product_type: product_type) 
end