我正在创建一个应用程序,允许用户记录锻炼和练习,练习作为我的锻炼表单中的嵌套模型。
routes.rb中:
resources :users do
resources :workouts
end
workouts.rb:
attr_accessible :name, :exercises_attributes
has_many :exercises
belongs_to :user
accepts_nested_attributes_for :exercises, :allow_destroy => true
exercise.rb:
attr_accessible :name, :weight, :reps
belongs_to :workout
在我的 workouts_controller.rb :
中def create
@workout = @user.workouts.new(workout_params)
@exercise = @workout.exercises.new(params[:workout][:exercise])
respond_to do |format|
if @workout.save && @exercise.save
//...etc
在我的锻炼/ _form.html.erb :
中<%= form_for [@user, @workout], builder: LabeledFormBuilder do |f| %>
<%= f.text_field :name %>
<%= f.fields_for :exercises do |builder| %>
<%= builder.text_field :name %>
<%= builder.text_field :weight %>
<%= builder.text_field :reps %>
<% end %>
<%= f.submit %>
<% end %>
我遇到问题让fields_for按照文档(http://edgeapi.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for)的规定工作。
它表示如果模型是一对多关联,您应该能够传递到fields_for你的模型的复数版本。这在我的锻炼#new action中运行良好,但在我的锻炼#edit中,我必须传入单一化版本(:exercise)才能显示对象的当前属性值(锻炼)。文档说:
通常只需传递模型的名称即可简化此操作 object to fields_for - ...在这种情况下,if:permission也会发生 是实例变量@permission的名称,初始状态为 输入字段将反映该变量属性的值 @ permission.admin。
传递:exercise到fields的练习不会将属性保存到数据库,而传递:exercise到fields_for会将其保存到数据库中,但不会在编辑操作中显示当前属性值。
在训练中#new和#edit: with fields_for:exercise
<div class="field"><input id="workout_exercise_name" name="workout[exercise][name]" placeholder="name" type="text" /></div>
使用fields_for:exercise
<div class="field"><input id="workout_exercises_attributes_0_name" name="workout[exercises_attributes][0][name]" placeholder="name" type="text" /></div>
最后,我在我的开发日志#create:
中有以下内容Started POST "/users/5/workouts" for 127.0.0.1 at 2013-04-07 14:13:45 -0400
Processing by WorkoutsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"a98ozlUWDtZc49v/PfFds/V0S56R2Y73HsxW6+wjYWI=", "workout"=>{"name"=>"test", "exercise"=>{"name"=>"lunge", "weight"=>"30", "reps"=>"20", "_destroy"=>""}}, "commit"=>"Create Workout", "user_id"=>"5"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", "5"]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."auth_token" = 'dHhQQSEecDOetjh-ZROpmw' LIMIT 1
Unpermitted parameters: exercise
WARNING: Can't mass-assign protected attributes for Exercise: _destroy
app/controllers/workouts_controller.rb:32:in `create'
(0.2ms) BEGIN
SQL (0.8ms) INSERT INTO "workouts" ("created_at", "name", "updated_at", "user_id") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Sun, 07 Apr 2013 18:13:45 UTC +00:00], ["name", "test"], ["updated_at", Sun, 07 Apr 2013 18:13:45 UTC +00:00], ["user_id", 5]]
SQL (0.6ms) INSERT INTO "exercises" ("created_at", "name", "reps", "updated_at", "weight", "workout_id") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["created_at", Sun, 07 Apr 2013 18:13:45 UTC +00:00], ["name", "lunge"], ["reps", 20], ["updated_at", Sun, 07 Apr 2013 18:13:45 UTC +00:00], ["weight", 30], ["workout_id", 64]]
(0.6ms) COMMIT
(0.4ms) BEGIN
(0.2ms) COMMIT
Redirected to http://localhost:3000/users/5/workouts
Completed 302 Found in 21ms (ActiveRecord: 3.5ms)
注意未经许可的参数:练习。
有谁知道为什么会这样?我很难过。任何帮助都会超级棒。如果没有人有任何想法,我可能会尝试创建一个新的rails 4应用程序并在那里测试这些关联。
答案 0 :(得分:1)
在rails 4应用程序中,您需要切换质量分配策略以使用强参数。这意味着从模型中删除attr_accessible并将它们放在控制器中。这就是你的日志在第6-7行告诉你的内容。
使用嵌套属性,控制器中的workout_params将看起来像这样:
private
def workout_params
params.require(:workout).permit(
:id,
:next_attribute,
:next_attribute,
exercises_attributes: [
:id,
:next_attribute,
:next_attribute
])
end
有很多资源可以获得有关强参数的更多信息 - 这里是来自Ryan Bates的资料:http://railscasts.com/episodes/371-strong-parameters