[英]How to create a child model from a parent
我已經旋轉了幾天就可以用Rails轉動輪子了。 我正在使用三種模型: IngredientBase
, Ingredient
和IngredientList
。 IngredientBase
包含可能是“雞”,“雞蛋”或“培根”的字符串。 成分將具有單一Ingredient
和數量。 IngredientList
將有許多成分。
我希望用戶能夠使用ingredient_lists / new並能夠在提交IngredientList之前創建多個IngredientList
。 如果沒有用戶提交多個表單,我怎么能這樣做?
聯想
你正在看的是嵌套模型 。
嵌套模型基本上允許您將屬性附加到一個模型的實例; 那些屬性被發送到關聯模型。
這是通過accepts_nested_attributes_for
實現的:
#app/models/ingredient_list.rb
class IngrendientList < ActiveRecord::Base
has_many :ingredients
accepts_nested_attributes_for :ingredients
end
#app/models/ingredient.rb
class Ingredient < ActiveRecord::Base
belongs_to :ingredient_list
end
因為你的模型讓我困惑,我為你重寫了結構。 我認為你對連接模型等感到困惑:
#app/models/ingredient.rb
class Ingredient < ActiveRecord::Base
#columns id | name | weight | etc | created_at | updated_at
has_many :recipe_ingredients
has_many :recipes, through: :recipe_ingredients
end
#app/models/recipe_ingredient.rb
class RecipeIngredient < ActiveRecord::Base
#columns id | recipe_id | ingredient_id | quantity | created_at | updated_at
belongs_to :recipe
belongs_to :ingredient
accepts_nested_attributes_for :ingredient
end
#app/models/recipe.rb
class Recipe < ActiveRecord::Base
#columns id | name | etc | etc | created_at | updated_at
has_many :recipe_ingredients #-> allows extra attributes
has_many :ingredients, through: :recipe_ingredients
accepts_nested_attributes_for :recipe_ingredients
end
這將使您能夠創建Recipe
,添加新的Ingredient
,並通常使您的模型更加健壯。
以下是如何使它與控制器和視圖等一起使用:
#app/controllers/recipes_controller.rb
class RecipesController < ApplicationController
def new
@recipe = Recipe.new
end
def create
@recipe = Recipe.new recipe_params
@recipe.save
end
private
def recipe_params
params.require(:recipe).permit(:recipe, :params, recipe_ingredients_attributes: [:quantity, ingredient_attributes:[:name]])
end
end
這將創建一個基本表單,但我們需要包含相關字段。 有幾種方法可以做到這一點,包括RailsCasts的“手動”方法和使用Cocoon 。
因此,需要注意的重要事項是:
每次調用嵌套表單字段時,基本上都是讓Rails將
f.fields_for
另一個實例添加到表單中。 這里要注意的重要的事情是你需要具備的CHILD_INDEXfields_for
塊。 這是Rails用於識別字段的內容,需要保持唯一。
你可以在一段時間內回答的問題上看到更多相關信息。
對於您的表單,您需要以下內容:
#app/views/recipes/new.html.erb
<%= form_for @recipe do |f| %>
<%= f.text_field :title %>
<%= render "ingredients", locals: {f: f, child_index: Time.now.to_i} %>
<%= link_to "Add Ingredient", recipes_add_field_path, class: "ingredient" %>
<%= f.submit %>
<% end %>
#app/views/recipes/_ingredients.html.erb
<%= f.fields_for :recipe_ingredients, child_index: child_index do |ri| %>
<%= ri.text_field :quantity %>
<%= ri.fields_for :ingredient do |ingredient| %>
<%= ingredient.text_field :name %>
<%= ingredient.text_field :weight %>
<% end %>
<% end %>
#config/routes.rb
resources :recipes do
member "add_field", to: "recipes#add_field"
end
#app/controllers/recipes_controller.rb
class RecipesController < ApplicationController
def add_field
@recipe = Recipe.new
@recipe.recipe_ingredients.build.build_ingredient
render "new"
end
end
#app/assets/javascripts/application.js
$(document).on("click", "a.ingredient", function(){
$.ajax({
url: '/recipes/add_field',
success: function(data){
el_to_add = $(data).html();
$('#recipes').append(el_to_add);
}
error: function(data){
alert("Sorry, There Was An Error!");
}
});
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.