简体   繁体   中英

What is the Correct Ruby on Rails Syntax to Write to a Nested Model within a Virtual Attribute?

Trying to divide and conquer these problems ( 1 , 2 ) I am still having. I would like to write the first step of a BLT recipe in my nested, many-to-many model from the virtual attribute. Later on I would like to have a more complex form, thus I am doing this in the model.

I have hard-coded everything in the model except for name of the recipe. Here is the Recipe model:

    class Recipe < ActiveRecord::Base
      has_many :steps, :class_name => 'Step'
      has_many :stepingreds, :through => :steps
      has_many :ingredients, :through => :stepingreds
      accepts_nested_attributes_for :steps, :stepingreds, :ingredients
      attr_writer :name_string
      after_save :assign_name

      def name_string
        self[:name]
      end

      def assign_name
        if @name_string
        self[:name] = @name_string
        self[:description] = "Addictive sandwich"
        self.steps = Step.create({
           :number => 1,
           :instructions => 'Cook bacon',
           :stepingreds => [{ :ingredient => { :name => 'Bacon' }, :amount => 4 } ]
          })
       end
    end

And here is the form

    <%= form_for @recipe do |f| %>
        <%= f.error_messages %>
        <p>
          <%= f.label :name_string, "Name" %><br/>
          <%= f.text_field :name_string %>
        </p>
        <p><%= f.submit %></p>
    <% end %>

I get a "NameError in RecipesController#create, undefined local variable or method `attribute' for #". I think I have more than one error but this seems like it should work to me. What am I doing wrong?

Thanks!

Edit - Here is the RecipeController create action

   def create
       @recipe = Recipe.new(params[:recipe])
       if @recipe.save
         redirect_to @recipe, :notice => "Delicious BLT created!"
       else
         render :action => 'new'
       end
     end                

I think one issue is the following line:

self.steps = Step.create(...

Steps are through your has_many association. So selft.steps will contain a list of zero-to-many steps. Your assignment through = is providing it with a single item, and that will break it. What you really want (I think) is to create self.steps as a list of one item, rather than one item. Changing the = assignment to << should accomplish that.

Here's a simple Rails application that does what you need:

https://github.com/pixeltrix/cookbook

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM