Как добавить has_many: через детали к форме RoR - PullRequest
0 голосов
/ 27 октября 2011

Я делаю то, что кажется обычным обучающим приложением для Ruby on Rails, приложением рецептов.В частности, работа над рецептами и ингредиентами как отношения has_many: through.Просматривая миллион примеров и вопросов, я установил свои отношения «многие ко многим» и свою многомодельную форму, но я хотел бы добавить дополнительное поле и не могу заставить его работать.Похоже, я близок к пониманию того, как это работает.Вот краткие сведения:

Модели:

class Ingredient < ActiveRecord::Base
  has_many :recipe_ingredients
  has_many :recipes, :through => :recipe_ingredients
end

class RecipeIngredient < ActiveRecord::Base
  belongs_to :recipe
  belongs_to :ingredient
end

class Recipe < ActiveRecord::Base
  has_many :recipe_ingredients
  has_many :ingredients, :through => :recipe_ingredients
  accepts_nested_attributes_for :ingredients, :recipe_ingredients

  def new_recipe_ingredient_attributes=(recipe_ingredient_attributes)
    recipe_ingredient_attributes.each do |attributes|
      recipe_ingredients.build(attributes)
    end
  end

  def existing_recipe_ingredient_attributes=(recipe_ingredient_attributes)
    recipe_ingredients.reject(&:new_record?).each do |recipe_ingredient|
      attributes = recipe_ingredient_attributes[recipe_ingredient.id.to_s]
      if attributes
        recipe_ingredient.attributes = attributes
      else
        recipe_ingredient.delete(recipe_ingredient)
      end
    end
  end

  def save_recipe_ingredients
    recipe_ingredients.each do |recipe_ingredient|
      recipe_ingredient.save(false)
    end
  end
end

Контроллер:

def create
   @recipe = Recipe.new(params[:recipe])
   if @recipe.save
         redirect_to :action => 'show', :id => @recipe
         flash[:notice] = "Your record has been saved."
   else
         render :action => 'new'
   end
end

def update
   params[:recipe][:existing_recipe_ingredient_attributes] ||= {}
   @recipe = Recipe.find(params[:id])
   if @recipe.update_attributes(params[:recipe])
      redirect_to :action => 'show', :id => @recipe
      flash[:notice] = "Your changes have been saved."
   else
      render :action => 'edit'
   end
end  

Вид:

<% form_for(@recipe) do |f| %>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
etc.....
    Ingredients:
    <div id="recipe_ingredients">
      <div class="recipe_ingredient">
      <% new_or_existing = recipe_ingredient.new_record? ? 'new' : 'existing' %>
      <% prefix = "recipe[#{new_or_existing}_recipe_ingredient_attributes][]" %>
      <% fields_for prefix, recipe_ingredient do |ri_form| %>
        <p>
          <%= ri_form.collection_select(:id, Ingredient.find(:all), :id, :name, :include_blank => true) %>
          <%= ri_form.text_field :amount %>
        </p>
      <% end %>
      </div>
    </div>
  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

Извините за стенукод, надеюсь, это имеет смысл.Я не могу понять, почему текстовое поле «количество» не работает.Я пробовал миллион разных способов, но не могу заставить его работать.В этом случае я получаю сообщение об ошибке: «неопределенный метод« сумма »для #»

Какое соединение с ключом мне здесь не хватает?Спасибо.

1 Ответ

0 голосов
/ 27 октября 2011

На первый взгляд кажется, что вы должны просто заменить:

      <% fields_for prefix, recipe_ingredient do |ri_form| %>

с:

      <%= fields_for prefix, recipe_ingredient do |ri_form| %>
...