2016-05-05 12 views
1

Ich bin neu auf Schienen, und ich war etwas zu bauen basiert weg von diesem Railscast,dynamische Formulare in Schienen, NoMethodError

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

Da dies sehr veraltet ist, ich bin nicht in der Lage eine der zum Download alte Edelsteine, auf die es angewiesen ist - zumindest mit RVM - also kann ich es nicht wirklich überprüfen.

Allerdings jemand aktualisiert es von Schienen 3 bis 4.2, https://github.com/asang/403-dynamic-forms, aber ich bekomme immer eine undefined method 'fields' for nil:NilClass Fehler.

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 

Auf einer Seite zur Frage, wenn sie von Schienen 3 Ändern 4,2 bis Schienen, wie funktioniert der product_field.rb Zugang der :field_type und :name, wenn es nicht einen Controller hat ?

Product_field.rb - Rails 3

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

Product_field.rb - Schienen 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 %> 

Log

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' 

Jemand auf Railscast hat einen Kommentar das gleiche Problem haben, andere antwortete, dass es zu tun habe mit dem Auslassen der <%= f.hidden_field :product_type_id %> bin ich etwas fehlt? Danke, dass du dir die Zeit genommen hast, über diesen höchstwahrscheinlich dummen Fehler nachzudenken.

Antwort

1

Das Problem ist, mit, wie Sie Ihre @product auf dieser Linie in ProductsController#new Instanziierung:

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

Sie Referenzierung der product_type durch seine ID, und nicht als konkrete Referenz. Da @ product nicht in Ihrer new Aktion gespeichert ist, wird @product.product_type nie aus der Datenbank geladen und wird immer nil sein. Um das Problem zu beheben, laden Sie das product_type und beziehen Sie es direkt von dem neuen Produkt:

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