Javascript 在Rails 4中使用JQuery以一种形式生成嵌套对象
使用Rails 4,并基于此,我试图通过Javascript使用单个表单动态创建父对象和子对象。我已经修改了Ryan Bate在其应用程序助手中的代码(与railscast插曲在同一页上),以便可以在一个表单中创建父对象(BudgetSegment)和子对象(BudgetRatio) 我希望有人看看我下面的Javascript 在Rails 4中使用JQuery以一种形式生成嵌套对象,javascript,jquery,ruby-on-rails-4,Javascript,Jquery,Ruby On Rails 4,使用Rails 4,并基于此,我试图通过Javascript使用单个表单动态创建父对象和子对象。我已经修改了Ryan Bate在其应用程序助手中的代码(与railscast插曲在同一页上),以便可以在一个表单中创建父对象(BudgetSegment)和子对象(BudgetRatio) 我希望有人看看我下面的link\u to\u add\u fields方法,告诉我哪里出了问题,因为它不起作用,并告诉我这是否是功能不起作用的罪魁祸首。是否您不能将builder.fields.for嵌套在下面的f
link\u to\u add\u fields
方法,告诉我哪里出了问题,因为它不起作用,并告诉我这是否是功能不起作用的罪魁祸首。是否您不能将builder.fields.for
嵌套在下面的f.fields\u中?以下是application\u helper.rb
中的相关代码:
def link_to_add_fields(name, f, association, nested_association, locals={})
new_object = f.object.class.reflect_on_association(association).klass.new
nested_new_object = f.object.class.reflect_on_association(association).klass.reflect_on_association(nested_association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
builder.fields_for(nested_association, nested_new_object, :child_index => "new_#{nested_association}") do |nested_builder|
render(association.to_s.singularize + "_row", locals.merge!(:ff => builder, :fff => nested_builder))
end
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{nested_association}\", \"#{escape_javascript(fields)}\")")
end
class BudgetSourcesController < ApplicationController
include ApplicationHelper
require 'debugger'
def new
@budget_source = BudgetSource.new
2.times { @budget_source.budget_sources_genres.build }
@budget_segment = @budget_source.budget_segments.build
scenarios.count.times { @budget_segment.budget_ratios.build }
render 'budget_sources/new'
end
def create
@budget_source = BudgetSource.create(budget_source_params)
@budget_source.update(:user_id => current_user.id)
@budget_source.budget_segments.order(:id).each do |bs|
bs.budget_ratios.order(:id).each_with_index do |br, i|
br.update(scenario_id: i+1)
end
end
render 'show'
end
def show
@budget_source = BudgetSource.find(params[:id])
render 'show'
end
private
def budget_source_params
params.require(:budget_source).permit(:id, :user_id, :name, :description, :territory_id, budget_sources_genres_attributes: [:id, :genre_id, :budget_source_id], budget_segments_attributes: [:id, :max, budget_ratios_attributes: [:id, :box_value, :pa_value, :budget_segment_id, :scenario_id]])
end
end
这是我的js文件:
function add_fields(link, association, nested_association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
var regexp2 = new RegExp("new_" + nested_association, "g")
$(link).parent().parent().parent().before().child(content.replace(regexp, new_id).replace(regexp2, new_id);
}
BudgetSegment和BudgetRatio都位于表的同一行上。目标是允许用户在单击“添加”按钮时动态创建一行新的文本字段。此行将同时在第一列中创建一个BudgetSegment文本字段,并在右边的列中创建数量不确定的BudgetTio文本字段(对于Javascript方法,我只假设创建了一个BudgetTio,尽管您将在budget\u source\u controller中看到,最初创建了五个BudgetTio)
此链接\u添加\u字段
代码应生成以下部分\u预算\u段\u row.html.erb
:
<tr class="table-financial">
<td><%= ff.text_field :max, :id => "form-currency", :class => "form-control", :placeholder => '"$1,000,000"', :required => :true %>
</td>
<%= ff.fields_for :budget_ratios do |fff| %>
<td><%= fff.text_field 'box_value', :class => "form-control", :placeholder => 'e.g., "0.75"' %></td>
<td><%= fff.text_field 'pa_value', :id => "pa-value", :class => "form-control", :placeholder => 'e.g., "0.75"' %></td>
<% end %>
</tr>
如您所见,BudgetRatio块中缺少任何内容
以下是我的模型结构(仅包括相关部分):
下面是预算来源控制者.rb
:
def link_to_add_fields(name, f, association, nested_association, locals={})
new_object = f.object.class.reflect_on_association(association).klass.new
nested_new_object = f.object.class.reflect_on_association(association).klass.reflect_on_association(nested_association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
builder.fields_for(nested_association, nested_new_object, :child_index => "new_#{nested_association}") do |nested_builder|
render(association.to_s.singularize + "_row", locals.merge!(:ff => builder, :fff => nested_builder))
end
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{nested_association}\", \"#{escape_javascript(fields)}\")")
end
class BudgetSourcesController < ApplicationController
include ApplicationHelper
require 'debugger'
def new
@budget_source = BudgetSource.new
2.times { @budget_source.budget_sources_genres.build }
@budget_segment = @budget_source.budget_segments.build
scenarios.count.times { @budget_segment.budget_ratios.build }
render 'budget_sources/new'
end
def create
@budget_source = BudgetSource.create(budget_source_params)
@budget_source.update(:user_id => current_user.id)
@budget_source.budget_segments.order(:id).each do |bs|
bs.budget_ratios.order(:id).each_with_index do |br, i|
br.update(scenario_id: i+1)
end
end
render 'show'
end
def show
@budget_source = BudgetSource.find(params[:id])
render 'show'
end
private
def budget_source_params
params.require(:budget_source).permit(:id, :user_id, :name, :description, :territory_id, budget_sources_genres_attributes: [:id, :genre_id, :budget_source_id], budget_segments_attributes: [:id, :max, budget_ratios_attributes: [:id, :box_value, :pa_value, :budget_segment_id, :scenario_id]])
end
end
class BudgetSourceControllercurrent\u user.id)
@预算|来源.预算|段.订单(:id).每个do | bs|
bs.预算比率.订单(:id).每个带有索引do | br,i的|
br.更新(场景id:i+1)
结束
结束
渲染“显示”
结束
def秀
@budget\u source=BudgetSource.find(参数[:id])
渲染“显示”
结束
私有的
def预算\来源\参数
参数require(:budget\u source)。permit(:id,:user\u id,:name,:description,:territory\u id,budget\u sources\u attributes:[:id,:genre\u id,:budget\u source\u id,:budget\u attributes:[:id,:box\u value,:pa\u value,:budget\u segment\u id,:scenario\u id])
结束
结束
这可能无法解决您的问题,但至少有助于提高可读性。尝试这样做:
new_object = f.const_get(association).new
nested_new_object = f.const_get(nested_association).new
# new_object = f.object.class.reflect_on_association(association).klass.new
# nested_new_object = f.object.class.reflect_on_association(association).klass.reflect_on_association(nested_association).klass.new
然而,我认为可能的问题是你正在传递fff:fff
locals.merge!(:ff => builder, :fff => nested_builder))
您使用的fff
唯一我能看到的地方就是在这个区块内:
<%= ff.fields_for :budget_ratios do |fff| %>
<td><%= fff.text_field 'box_value', :class => "form-control", :placeholder => 'e.g., "0.75"' %></td>
<td><%= fff.text_field 'pa_value', :id => "pa-value", :class => "form-control", :placeholder => 'e.g., "0.75"' %></td>
<% end %>
“表单控件”:占位符=>'例如,“0.75”%>
“pa值”、:类=>“表单控件”、:占位符=>”例如,“0.75”%>
但正如你所知,块内的fff不是你要经过的fff
。可能不是错误,但看起来可能是疏忽。也许你想在f
和ff
此外,这里还有一个三重嵌套表单的示例,它将新项添加到表中的偶数。也许有助于了解:
下面是我们用来添加/删除项目的javascript
事件的创建视图:
部分用于底部的add_项,其中包含第三个嵌套。
虽然这不是我想要的解决方案(我真的想知道为什么不能使用builder嵌套对象),但我的快速解决方案是: 我使用
[object].object.association.build
方法创建了一个嵌套对象,而不是将f.fields\u嵌套在do | f |
块的fields\u中(与视图中的常规方法相同)
您将注意到一个以array
开头的新行,因为我想同时创建定义数量的对象,所以我将一个iterator
变量传递到方法中,该变量基本上只是一个整数。这是我修订的链接到添加字段
代码:
def add_row(name, f, association, nested_association, iterator)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, child_index: "new_#{association}") do |bs|
array = eval("iterator.map {bs.object.#{nested_association}.build}")
render(association.to_s.singularize + "_row", {f: f, ff: bs, fff: array})
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")")
end
感谢您深入研究代码,不幸的是,它没有解决问题。分部应该生成“fff”本身,但是,这些对象(因为它们最初不是在控制器中构建的)必须单独构建。这就是为什么我在方法中创建它们,并尝试将它们作为本地人推送。
def add_row(name, f, association, nested_association, iterator)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, child_index: "new_#{association}") do |bs|
array = eval("iterator.map {bs.object.#{nested_association}.build}")
render(association.to_s.singularize + "_row", {f: f, ff: bs, fff: array})
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")")
end