我试图让用户通过各自的连接表(exercise_equipment,exercise_muscles)以多对多的关系创建设备和肌肉练习。我已经得到了每个练习添加一个设备/肌肉的表单,但是无法弄清楚如何添加链接以便在动态中向表单添加另一个字段。
我已经检出RailsCasts,this post,已将其作为previous post of my own的附带问题提出,但根本无法使此功能正常运行。我是Rails 4的新手,我还在尝试学习Javascript,但我非常喜欢对如何设置Rails 4的方式进行彻底的解释!
我的模特:
# 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
@exercise.exercise_muscles.build
end
def create
exercise = current_user.exercises.new( exercise_params )
if exercise.save!
redirect_to exercise
else
render 'new'
end
end
视图/练习/ new.html.erb
<h1>Create New Exercise</h1>
<%= 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, autofocus: true %>
<%= f.check_box :is_public %> Public
<%= f.fields_for :exercise_muscles do |emf| %>
<%= emf.collection_select :muscle_id, Muscle.all, :id, :name, { include_hidden: false } %>
<% end %>
<%= f.fields_for :exercise_equipment do |eef| %>
<%= eef.collection_select :equipment_id, Equipment.all, :id, :name, { include_hidden: false } %>
<%= eef.check_box :optional %> Optional
<% end %>
答案 0 :(得分:2)
<强>的Ajax 强>
无法弄清楚如何添加链接以向表单添加其他字段 在飞行中
&#34; Rails方式&#34;做到这一点就是&#34;拉&#34;来自fields_for
请求的ajax
块的新实例。
推荐使用Ajax的原因是因为它是&#34; Rails方式&#34;要做到这一点 - 完全模块化和可扩展的:
#config/routes.rb
resources :exercises do
get :add_field, on: :collection
end
#app/models/exercise.rb
Class Exercise < ActiveRecord::Base
...
def self.build #-> allows you to call a single method
exercise = self.new
exercise.exercise_equipment.build
exercise.exercise_muscles.build
return
end
end
#app/controllers/exercises_controller.rb
Class ExercisesController < ApplicationController
def add_field
@exercise = Exercise.build
respond_to do |format|
format.html
format.js
end
end
end
#app/views/exercises/new.html.erb
<%= form_for @exercise do |f| %>
<%= render "fields", locals: { f: f } %>
<%= f.submit %>
<% end %>
#app/views/exercises/add_field.js.erb
$("#form_element").append("<%=j render "exercises/form", locals: { exercise: @exercise } %>");
#app/views/exercises/_form.html.erb
<%= form_for exercise do |f| %>
<%= render "fields", locals: { f: f } %>
<% end %>
#app/views/exercises/_fields.html.erb
<%= f.fields_for :exercise_muscles, child_index: Time.now.to_i do |emf| %>
<%= emf.collection_select :muscle_id, Muscle.all, :id, :name, { include_hidden: false } %>
<% end %>
<%= link_to "New Field", exercises_add_fields_path, remote: :true %>
<%= f.fields_for :exercise_equipment, child_index: Time.now.to_i do |eef| %>
<%= eef.collection_select :equipment_id, Equipment.all, :id, :name, { include_hidden: false } %>
<%= eef.check_box :optional %> Optional
<% end %>
<%= link_to "New Field", exercises_add_fields_path, remote: :true %>
这将使您能够通过ajax调用创建字段;这是正确的做法
答案 1 :(得分:1)
尝试使用Rich的解决方案后,我想找到一个在使用的代码方面稍微简单一点的解决方案。我发现了宝石Cocoon,它很有效,并且很容易整合。
我的主要_form视图:
<div class="form-group">
<%= f.label :name %><br />
<%= f.text_field :name, autofocus: true %>
</div>
<div class="form-group">
<%= f.check_box :is_public %> Public
</div>
<div class="form-group">
<%= f.fields_for :exercise_muscles do |emf| %>
<%= render 'exercise_muscle_fields', :f => emf %>
<% end %>
<%= link_to_add_association 'Add Muscle', f, :exercise_muscles %>
</div>
<div class="form-group">
<%= f.fields_for :exercise_equipment do |eef| %>
<%= render 'exercise_equipment_fields', :f => eef %>
<% end %>
<%= link_to_add_association 'Add Equipment', f, :exercise_equipment %>
</div>
从这里可以看出,添加一个简单的“link_to_add_association”方法可以处理后台的所有Javascript。对于未来的读者,以下是每个表单组包含的部分内容:
_exercise_muscle_fields:
<%= f.collection_select :muscle_id, Muscle.all.order( 'muscle_group_id ASC' ), :id, :name, { include_hidden: false } %>
_exercise_equipment_fields:
<%= f.collection_select :equipment_id, Equipment.all.order( 'name ASC' ), :id, :name, { include_hidden: false } %>
<%= f.check_box :optional %> Optional