我正在构建一个配方管理器作为第一个rails应用程序。基于这个相当不错的ERD,我有一个多对多嵌套模型。理想情况下,我想创建一个允许我以单一形式创建配方的表单。另外,我希望用户能够分别将成分和步骤写入/粘贴到单个文本字段中。在下面的代码中,有一个虚拟属性可以分析表单中的cr分隔列表来尝试此操作。如何在Rails 3.1中编写简单的嵌套,has_many:through,多对多表单?
当我编写配料时,我不断收到“readonly”has_many错误。我明白,基于我脱机的优秀帮助,我的连接没有正确设置。
为简化操作,我希望将配料列表分配到第一步或每一步。 如何编写代码以便使用虚拟属性手动创建联接模型?
我的四种模式:
recipe.rb
class Recipe < ActiveRecord::Base
has_many :steps, :dependent => :destroy
has_many :stepingreds, :through => :steps
has_many :ingredients, :through => :stepingreds
validates_presence_of :name, :description
attr_writer :step_instructions, :ingredient_names
after_save :assign_steps, :assign_ingredients
def step_instructions
@step_instruction || steps.map(&:instruction).join("\n")
end
def ingredient_names
@ingredient_name || ingredients.map(&:name).join("\n")
end
private
def assign_steps
if @step_instructions
self.steps = @step_instructions.split(/\n+/).map do |instruction|
Step.find_or_create_by_instruction(instruction)
end
end
end
def assign_ingredients
if @ingredient_names
self.ingredients = @ingredient_names.split(/\n+/).map do |name|
Ingredient.find_or_create_by_name(name)
end
end
end
end
step.rb
class Step < ActiveRecord::Base
#attr_accessible :recipe_id, :number, :instructions
belongs_to :recipe
has_many :stepingreds, :class_name => 'Stepingred'
has_many :ingredients, :through => :stepingreds
end
stepingred.rb
class Stepingred < ActiveRecord::Base
belongs_to :ingredient
belongs_to :step, :class_name => 'Step'
end
ingredient.rb
class Ingredient < ActiveRecord::Base
has_many :stepingreds
has_many :steps, :through => :stepingred
has_many :recipes, :through => :steps
end
这里是我的精简形式:
<%= form_for @recipe do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description, :rows => 4 %>
</p>
<p>
<%= f.label :ingredient_names, "Ingredients" %><br />
<%= f.text_area :ingredient_names, :rows => 8 %>
</p>
<p>
<%= f.label :step_instructions, "Instructions" %><br />
<%= f.text_area :step_instructions, :rows => 8 %>
</p>
<p><%= f.submit %></p>
<% end %>
我的数据库模式:
ActiveRecord::Schema.define(:version => 20110714095329) do
create_table "ingredients", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "recipes", :force => true do |t|
t.string "name"
t.text "description"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "stepingreds", :force => true do |t|
t.integer "recipe_id"
t.integer "step_id"
t.integer "ingredient_id"
t.float "amount"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "steps", :force => true do |t|
t.integer "recipe_id"
t.integer "number"
t.text "instruction"
t.datetime "created_at"
t.datetime "updated_at"
end
end
请让我知道如果您有任何建议或可推荐另一块示例代码之后我可以模拟这个应用程序。
谢谢你的回答。我添加了'accep_nested ...'并将'Ingredient.find_or_create_by_name(name)'改成了'self.steps.create(:stepingreds => [{:ingredient => {:name => name}}])''based on my my阅读api。我现在在RecipesController中得到一个错误'NameError#为#创建未定义的局部变量或方法'属性'我是否正确写入嵌套数组?这个错误告诉你什么?日志没有提到试图插入到配料表中,所以我必须创建不正确的记录。再次感谢。 –
JHo
记得接受答案 – imjp
很难说在没有在应用中看到完整代码的情况下导致此错误的是什么。通常,该错误是在堆栈跟踪中输入一个行号。你能否将你的应用程序的副本推送到github存储库,并采取步骤正确地重现它以供我查看它? – Joey