生成 nested_form.js 文件
rails g nested_form:install
这是源代码:
module NestedForm
module Generators
class InstallGenerator < Rails::Generators::Base
def self.source_root
File.expand_path('../../../../vendor/assets/javascripts', __FILE__)
end
def copy_jquery_file
if File.exists?('public/javascripts/prototype.js')
copy_file 'prototype_nested_form.js', 'public/javascripts/nested_form.js'
else
copy_file 'jquery_nested_form.js', 'public/javascripts/nested_form.js'
end
end
end
end
end
增加 4 个辅助方法
(中间 两个 与 ‘SimpleForm’ 或 ‘Formtastic’ 相关)
require 'nested_form/builders'
module NestedForm
module ViewHelper
def nested_form_for(*args, &block)
options = args.extract_options!.reverse_merge(:builder => NestedForm::Builder)
form_for(*(args << options), &block) << after_nested_form_callbacks
end
if defined?(NestedForm::SimpleBuilder)
def simple_nested_form_for(*args, &block)
options = args.extract_options!.reverse_merge(:builder => NestedForm::SimpleBuilder)
simple_form_for(*(args << options), &block) << after_nested_form_callbacks
end
end
if defined?(NestedForm::FormtasticBuilder)
def semantic_nested_form_for(*args, &block)
options = args.extract_options!.reverse_merge(:builder => NestedForm::FormtasticBuilder)
semantic_form_for(*(args << options), &block) << after_nested_form_callbacks
end
end
def after_nested_form(association, &block)
@associations ||= []
@after_nested_form_callbacks ||= []
unless @associations.include?(association)
@associations << association
@after_nested_form_callbacks << block
end
end
private
def after_nested_form_callbacks
@after_nested_form_callbacks ||= []
fields = @after_nested_form_callbacks.map do |callback|
callback.call
end
fields.join(" ").html_safe
end
end
end
还‘赠送’以下 4 个方法
module NestedForm
module BuilderMixin
# Adds a link to insert a new associated records. The first argument is the name of the link, the second is the name of the association.
#
# f.link_to_add("Add Task", :tasks)
#
# You can pass HTML options in a hash at the end and a block for the content.
#
# <%= f.link_to_add(:tasks, :class => "add_task", :href => new_task_path) do %>
# Add Task
# <% end %>
#
# See the README for more details on where to call this method.
def link_to_add(*args, &block)
options = args.extract_options!.symbolize_keys
association = args.pop
options[:class] = [options[:class], "add_nested_fields"].compact.join(" ")
options["data-association"] = association
args << (options.delete(:href) || "javascript:void(0)")
args << options
@fields ||= {}
@template.after_nested_form(association) do
model_object = object.class.reflect_on_association(association).klass.new
output = %Q[<div id="#{association}_fields_blueprint" style="display: none">].html_safe
output << fields_for(association, model_object, :child_index => "new_#{association}", &@fields[association])
output.safe_concat('</div>')
output
end
@template.link_to(*args, &block)
end
# Adds a link to remove the associated record. The first argment is the name of the link.
#
# f.link_to_remove("Remove Task")
#
# You can pass HTML options in a hash at the end and a block for the content.
#
# <%= f.link_to_remove(:class => "remove_task", :href => "#") do %>
# Remove Task
# <% end %>
#
# See the README for more details on where to call this method.
def link_to_remove(*args, &block)
options = args.extract_options!.symbolize_keys
options[:class] = [options[:class], "remove_nested_fields"].compact.join(" ")
args << (options.delete(:href) || "javascript:void(0)")
args << options
hidden_field(:_destroy) + @template.link_to(*args, &block)
end
def fields_for_with_nested_attributes(association_name, *args)
# TODO Test this better
block = args.pop || Proc.new { |fields| @template.render(:partial => "#{association_name.to_s.singularize}_fields", :locals => {:f => fields}) }
@fields ||= {}
@fields[association_name] = block
super(association_name, *(args << block))
end
def fields_for_nested_model(name, object, options, block)
output = '<div class="fields">'.html_safe
output << super
output.safe_concat('</div>')
output
end
end
end