非常新的Rails 4开发人员。我有一个用户正在创建练习的表单。练习可以有很多设备,而设备可以是可选的(想想俯卧撑是做俯卧撑)。我将此“可选”字段存储在连接表exercise_equipment上。
我无法获取参数来实际发送我选择的集合元素的值。请参阅下面的模型,视图,控制器和参数。
以下是我的模型的属性/关系:
# id :integer
# name :string
# is_public :boolean
Exercise
has_many :exercise_equipment
has_many :equipment, :through => :exercise_equipment
accepts_nested_attributes_for :exercise_equipment
# id :integer
# exercise_id :integer
# equipment_id :integer
# optional :boolean
ExerciseEquipment
belongs_to :exercise
belongs_to :equipment
accepts_nested_attributes_for :equipment
# id :integer
# name :string
Equipment
has_many :exercise_equipment
has_many :exercises, :through => :exercise_equipment
以下是一些(可能)相关的控制器方法:
def new
@exercise = Exercise.new
@exercise.exercise_equipment.build
end
def create
@exercise = Exercise.new( exercise_params )
if @exercise.save
redirect_to @exercises
else
render 'new'
end
end
def edit
@exercise = Exercise.find( params[:id] )
end
def update
@exercise = Exercise.find( params[:id] )
if @exercise.update_attributes( exercise_params )
redirect_to @exercises
else
render 'edit'
end
end
def exercise_params
params.require( :exercise ).permit(
:name,
:is_public,
exercise_equipment_attributes: [
:id,
:optional,
equipment_attributes: [
:id,
:name
],
]
)
end
这是我创建视图以实现我想要的目标:
行使/ new.html.erb
<%= form_for @exercise do |f| %>
<%= render 'form', f: f %>
<%= f.submit "New Exercise" %>
<% end %>
行使/ _form.html.erb
<%= f.label :name %><br />
<%= f.text_field :name %>
<%= f.check_box :is_public %> Public
<%= f.fields_for( :exercise_equipment ) do |eef|
<%= eef.fields_for( :equipment ) do |ef|
ef.collection_select :id, Equipment.all, :id, :name %>
<% end %>
<%= eef.check_box :is_optional %> Optional
<% end %>
当我将所有这些放在一起并向已经存在的练习提交更新时,这些值都会通过params哈希值,但不会更改为我选择的新值...
Parameters: {
"utf8"=>"[checkbox]",
"authenticity_token"=>"[token]",
"exercise"=>{
"name"=>"Test",
"is_public"=>"1",
"exercise_equipment_attributes"=>{
"0"=>{
"equipment_attributes"=>{
"id"=>"1"
},
"optional"=>"1",
"id"=>"2"
}
}
},
"commit"=>"Save Exercise",
"id"=>"1"
}
如果你可以帮助我,我会非常感激。如果您需要更多信息,请告诉我,我可以提供。
修改
以下是更新前数据库的状态:
postgres@=>db=# select id, name, is_public from exercises;
id | name | is_public
----+------+-----------
2 | Test | t
(1 row)
Time: 61.279 ms
postgres@=>db=# select id, exercise_id, equipment_id, optional from exercise_equipment;
id | exercise_id | equipment_id | optional
----+-------------+--------------+----------
2 | 2 | 1 | t
(1 row)
Time: 58.819 ms
postgres@=>db=# select id, name from equipment where id = 1;
id | name
----+-------------
1 | Freeweights
(1 row)
然后我转到该练习的更新路线,从集合中选择不同的设备,然后提交表单。我得到以下Rails控制台结果:
Started PATCH "/exercises/system-test" for 127.0.0.1 at 2014-08-12 23:48:18 -0400
Processing by ExercisesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"PsbbUPSCiIew2Fd22Swn+K4PmLjwNDCrDdwXf9YBcm8=", "exercise"=>{"name"=>"Test", "is_public"=>"1", "exercise_equipment_attributes"=>{"0"=>{"equipment_attributes"=>{"id"=>"1"}, "optional"=>"1", "id"=>"2"}}}, "commit"=>"Save Exercise", "id"=>"system-test"}
Exercise Load (60.5ms) SELECT "exercises".* FROM "exercises" WHERE "exercises"."slug" = 'system-test' ORDER BY "exercises"."id" ASC LIMIT 1
(57.3ms) BEGIN
ExerciseEquipment Load (76.2ms) SELECT "exercise_equipment".* FROM "exercise_equipment" WHERE "exercise_equipment"."exercise_id" = $1 AND "exercise_equipment"."id" IN (2) [["exercise_id", 2]]
Equipment Load (59.1ms) SELECT "equipment".* FROM "equipment" WHERE "equipment"."id" = $1 LIMIT 1 [["id", 1]]
User Load (60.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 10]]
Exercise Exists (60.5ms) SELECT 1 AS one FROM "exercises" WHERE ("exercises"."name" = 'Test' AND "exercises"."id" != 2 AND "exercises"."user_id" = 10) LIMIT 1
(64.8ms) COMMIT
Redirected to http://localhost:3000/exercises/system-test
Completed 302 Found in 590ms (ActiveRecord: 580.0ms)
Started GET "/exercises/system-test" for 127.0.0.1 at 2014-08-12 23:48:19 -0400
Processing by ExercisesController#show as HTML
Parameters: {"id"=>"system-test"}
Exercise Load (64.1ms) SELECT "exercises".* FROM "exercises" WHERE "exercises"."slug" = 'system-test' ORDER BY "exercises"."id" ASC LIMIT 1
Equipment Load (58.7ms) SELECT "equipment".* FROM "equipment" INNER JOIN "exercise_equipment" ON "equipment"."id" = "exercise_equipment"."equipment_id" WHERE "exercise_equipment"."exercise_id" = $1 [["exercise_id", 2]]
Rendered exercises/show.html.erb within layouts/application (122.7ms)
User Load (60.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 10 ORDER BY "users"."id" ASC LIMIT 1
Rendered shared/_header.html.erb (61.9ms)
Rendered shared/_alerts.html.erb (0.1ms)
Completed 200 OK in 264ms (Views: 21.3ms | ActiveRecord: 240.8ms)
答案 0 :(得分:1)
首先,您需要确保正确定义关联。
任何has_many
关联都应使用复数名称定义 -
#app/models/exercise.rb
Class Exercise < ActiveRecord::Base
has_many :exercise_equipments
has_many :equipments, :through => :exercise_equipments
accepts_nested_attributes_for :exercise_equipments
end
#app/models/exercise_equipment.rb
Class ExerciseEquipment < ActiveRecord::Base
belongs_to :exercise
belongs_to :equipment
end
#app/models/equipment.rb
Class Equipment < ActiveRecord::Base
has_many :exercise_equipments
has_many :exercises, through: :exercise_equipments
end
如果您已经使用它,并且对您所拥有的内容感到满意,那么我建议您保留当前的设置。但是,您可能希望采用上述convention's缘故
编辑我从已删除的答案中看到Beartech
对此进行了调查,结果表明Rails将设备/设备视为相同。值得忽视上述内容,但我会将其留待将来参考
<强> PARAMS 强>
我无法获取实际发送的参数值 我选择的集合元素。请参阅下面的模型,视图, 控制器和参数。
我想我明白你的意思 - 你正在寻找更新记录,但它不会通过更新的参数发送给你的控制器,从而阻止它被更新。
虽然我无法看到任何明显的问题,但我建议问题是您尝试填充exercise_id
对象的Exercise
。您需要为exercise_equipment
对象定义它:
<%= f.fields_for :exercise_equipment do |eef| %>
<%= eef.collection_select :equipment_id, Equipment.all, :id, :name %>
<%= eef.check_box :is_optional %>
<% end %>
这将填充您的exercise_equipment
表,如下所述:
Time: 61.279 ms
postgres@=>db=# select id, exercise_id, equipment_id, optional from exercise_equipment;
id | exercise_id | equipment_id | optional
----+-------------+--------------+----------
2 | 2 | 1 | t
(1 row)
目前,您正在使用Equipment
填充equipment_id
模型 - 这不会起作用。以这种方式填充模型将服务器创建新记录,而不是更新已创建的记录
额外字段
我希望有一个链接来添加额外的设备字段 点击,类似于Ryan Bates在这个RailsCast中的表现,但是 他写的帮助方法(如果你没有订阅,请参阅&#34;显示注释&#34;标签 当看到来源时,似乎变得更加复杂 处理下面代码中显示的嵌套视图。任何帮助 处理这件事?
这是一个难以克服的山峰
Ryan在这个过程中使用了一个过时的方法(预先填充链接,然后让JS追加该字段)。 &#34;权利&#34;方法是建立一个新的对象&amp;从ajax附加fields_for
。听起来很难?那是因为它是:)
以下是您的工作方式:
#config/routes.rb
resources :exercises do
collection do
get :ajax_update #-> domain.com/exercises/ajax_update
end
end
#app/models/exercise.rb
Class Exercise < ActiveRecord::Base
def self.build
exercise = self.new
exercise.exercise_equipment.build
end
end
#app/controllers/exercises_controller.rb
Class ExercisesController < ApplicationController
def new
@exercise = Exercise.build
end
def ajax_update
@exercise = Exercise.build
render "add_exercise", layout: false #> renders form with fields_for
end
end
#app/views/exercises/add_exercise.html.erb
<%= form_for @exercise do |f| %>
<%= render partial: "fields_for", locals: { form: f } %>
<% end %>
#app/views/exercises/_fields_for.html.erb
<%= f.fields_for :exercise_equipment, child_index: Time.now.to_i do |eef| %>
<%= eef.collection_select :equipment_id, Equipment.all, :id, :name %>
<%= eef.check_box :is_optional %>
<% end %>
#app/views/exercises/edit.html.erb
<%= form_for @exercise do |f| %>
<%= render partial: "fields_for", locals: { form: f } %>
<%= link_to "Add Field", "#", id: "add_field" %>
<% end %>
#app/assets/javascripts/application.js
$(document).on("click", "#add_field", function() {
$.ajax({
url: "exercises/ajax_update",
success: function(data) {
el_to_add = $(data).html()
$('#your_id').append(el_to_add)
}
});
});