diff --git a/Gemfile b/Gemfile
index f5191458..c185f2e0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,4 +2,4 @@ gemspec :path => '.'
instance_eval File.read(File.expand_path('../gemfiles/Gemfile.base', __FILE__))
-gem 'rails', '~> 3.2.0'
+gem 'rails', '~> 4.0.0'
diff --git a/lib/nested_form/builder_mixin.rb b/lib/nested_form/builder_mixin.rb
index b572cf07..8df7fe7d 100644
--- a/lib/nested_form/builder_mixin.rb
+++ b/lib/nested_form/builder_mixin.rb
@@ -1,22 +1,22 @@
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.
+ # Adds a button 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)
+ # f.button_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 %>
+ # <%= f.button_to_add(:tasks, :class => "add_task", :href => new_task_path) do %>
# Add Task
# <% end %>
#
# You can also pass model_object option with an object for use in
# the blueprint, e.g.:
#
- # <%= f.link_to_add(:tasks, :model_object => Task.new(:name => 'Task')) %>
+ # <%= f.button_to_add(:tasks, :model_object => Task.new(:name => 'Task')) %>
#
# See the README for more details on where to call this method.
- def link_to_add(*args, &block)
+ def button_to_add(*args, &block)
options = args.extract_options!.symbolize_keys
association = args.pop
@@ -31,8 +31,8 @@ def link_to_add(*args, &block)
options[:class] = [options[:class], "add_nested_fields"].compact.join(" ")
options["data-association"] = association
+ options["type"] = "button"
options["data-blueprint-id"] = fields_blueprint_id = fields_blueprint_id_for(association)
- args << (options.delete(:href) || "javascript:void(0)")
args << options
@fields ||= {}
@@ -43,21 +43,21 @@ def link_to_add(*args, &block)
blueprint[:"data-blueprint"] = fields_for(association, model_object, options, &block).to_str
@template.content_tag(:div, nil, blueprint)
end
- @template.link_to(*args, &block)
+ @template.button_tag(*args, &block)
end
- # Adds a link to remove the associated record. The first argment is the name of the link.
+ # Adds a button to remove the associated record. The first argment is the name of the link.
#
- # f.link_to_remove("Remove Task")
+ # f.button_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 %>
+ # <%= f.button_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)
+ def button_to_remove(*args, &block)
options = args.extract_options!.symbolize_keys
options[:class] = [options[:class], "remove_nested_fields"].compact.join(" ")
@@ -65,10 +65,24 @@ def link_to_remove(*args, &block)
md = object_name.to_s.match /(\w+)_attributes\]\[[\w\d]+\]$/
association = md && md[1]
options["data-association"] = association
+ options["type"] = "button"
- args << (options.delete(:href) || "javascript:void(0)")
args << options
- hidden_field(:_destroy) << @template.link_to(*args, &block)
+ hidden_field(:_destroy) << @template.button_tag(*args, &block)
+ end
+
+ def button_to_diable(*args, &block)
+ options = args.extract_options!.symbolize_keys
+ options[:class] = [options[:class], "remove_nested_fields"].compact.join(" ")
+
+ # Extracting "milestones" from "...[milestones_attributes][...]"
+ md = object_name.to_s.match /(\w+)_attributes\]\[[\w\d]+\]$/
+ association = md && md[1]
+ options["data-association"] = association
+ options["type"] = "button"
+
+ args << options
+ hidden_field(:disabled) << @template.button_tag(*args, &block)
end
def fields_for_with_nested_attributes(association_name, *args)
diff --git a/spec/dummy/app/views/companies/new.html.erb b/spec/dummy/app/views/companies/new.html.erb
index 682e2f80..6d985c65 100644
--- a/spec/dummy/app/views/companies/new.html.erb
+++ b/spec/dummy/app/views/companies/new.html.erb
@@ -6,11 +6,11 @@
<%= tf.text_field :name %>
<%= tf.fields_for :milestones do |mf| %>
<%= mf.text_field :name %>
- <%= mf.link_to_remove 'Remove milestone' %>
+ <%= mf.button_to_remove 'Remove milestone' %>
<% end %>
- <%= tf.link_to_add 'Add new milestone', :milestones %>
- <%= tf.link_to_remove 'Remove' %>
+ <%= tf.button_to_add 'Add new milestone', :milestones %>
+ <%= tf.button_to_remove 'Remove' %>
<% end -%>
- <%= pf.link_to_add 'Add new task', :tasks %>
+ <%= pf.button_to_add 'Add new task', :tasks %>
<% end -%>
<% end -%>
diff --git a/spec/dummy/app/views/projects/new.html.erb b/spec/dummy/app/views/projects/new.html.erb
index bf87f630..8b062741 100644
--- a/spec/dummy/app/views/projects/new.html.erb
+++ b/spec/dummy/app/views/projects/new.html.erb
@@ -4,10 +4,10 @@
<%= tf.text_field :name %>
<%= tf.fields_for :milestones do |mf| %>
<%= mf.text_field :name %>
- <%= mf.link_to_remove 'Remove milestone' %>
+ <%= mf.button_to_remove 'Remove milestone' %>
<% end %>
- <%= tf.link_to_add 'Add new milestone', :milestones %>
- <%= tf.link_to_remove 'Remove' %>
+ <%= tf.button_to_add 'Add new milestone', :milestones %>
+ <%= tf.button_to_remove 'Remove' %>
<% end -%>
- <%= f.link_to_add 'Add new task', :tasks %>
+ <%= f.button_to_add 'Add new task', :tasks %>
<% end -%>
diff --git a/spec/dummy/app/views/projects/without_intermediate_inputs.html.erb b/spec/dummy/app/views/projects/without_intermediate_inputs.html.erb
index c3db2e8e..e2be571c 100644
--- a/spec/dummy/app/views/projects/without_intermediate_inputs.html.erb
+++ b/spec/dummy/app/views/projects/without_intermediate_inputs.html.erb
@@ -2,10 +2,10 @@
<%= f.fields_for :tasks do |tf| -%>
<%= tf.fields_for :milestones do |mf| %>
<%= mf.text_field :name %>
- <%= mf.link_to_remove 'Remove milestone' %>
+ <%= mf.button_to_remove 'Remove milestone' %>
<% end %>
- <%= tf.link_to_add 'Add new milestone', :milestones %>
- <%= tf.link_to_remove 'Remove' %>
+ <%= tf.button_to_add 'Add new milestone', :milestones %>
+ <%= tf.button_to_remove 'Remove' %>
<% end -%>
- <%= f.link_to_add 'Add new task', :tasks %>
+ <%= f.button_to_add 'Add new task', :tasks %>
<% end -%>
diff --git a/spec/events_spec.rb b/spec/events_spec.rb
index bad25c9c..df3478db 100644
--- a/spec/events_spec.rb
+++ b/spec/events_spec.rb
@@ -14,19 +14,19 @@
context 'when field was added' do
it 'emits general add event' do
visit url
- click_link 'Add new task'
+ click_button 'Add new task'
page.should have_content 'Added some field'
end
it 'emits add event for current association' do
visit url
- click_link 'Add new task'
+ click_button 'Add new task'
page.should have_content 'Added task field'
page.should_not have_content 'Added milestone field'
- click_link 'Add new milestone'
+ click_button 'Add new milestone'
page.should have_content 'Added milestone field'
end
@@ -35,26 +35,26 @@
context 'when field was removed' do
it 'emits general remove event' do
visit url
- click_link 'Add new task'
- click_link 'Remove'
+ click_button 'Add new task'
+ click_button 'Remove'
page.should have_content 'Removed some field'
end
it 'emits remove event for current association' do
visit url
- 2.times { click_link 'Add new task' }
- click_link 'Remove'
+ 2.times { click_button 'Add new task' }
+ click_button 'Remove'
page.should have_content 'Removed task field'
page.should_not have_content 'Removed milestone field'
- click_link 'Add new milestone'
- click_link 'Remove milestone'
+ click_button 'Add new milestone'
+ click_button 'Remove milestone'
page.should have_content 'Removed milestone field'
end
end
end
end
-end
\ No newline at end of file
+end
diff --git a/spec/form_spec.rb b/spec/form_spec.rb
index 2701051b..502db409 100644
--- a/spec/form_spec.rb
+++ b/spec/form_spec.rb
@@ -5,17 +5,17 @@
def check_form
page.should have_no_css('form .fields input[id$=name]')
- click_link 'Add new task'
+ click_button 'Add new task'
page.should have_css('form .fields input[id$=name]', :count => 1)
find('form .fields input[id$=name]').should be_visible
find('form .fields input[id$=_destroy]').value.should == 'false'
- click_link 'Remove'
+ click_button 'Remove'
find('form .fields input[id$=_destroy]').value.should == '1'
find('form .fields input[id$=name]').should_not be_visible
- click_link 'Add new task'
- click_link 'Add new task'
+ click_button 'Add new task'
+ click_button 'Add new task'
fields = all('form .fields')
fields.select { |field| field.visible? }.count.should == 2
fields.reject { |field| field.visible? }.count.should == 1
@@ -33,32 +33,32 @@ def check_form
it 'works when there are no inputs for intermediate association', :js => true do
visit '/projects/without_intermediate_inputs'
- click_link 'Add new task'
- click_link 'Add new milestone'
- click_link 'Add new milestone'
+ click_button 'Add new task'
+ click_button 'Add new milestone'
+ click_button 'Add new milestone'
inputs = all('.fields .fields input[id$=name]')
inputs.first[:name].should_not eq(inputs.last[:name])
end
it 'generates correct name for the nested input', :js => true do
visit '/projects/new?type=jquery'
- click_link 'Add new task'
- click_link 'Add new milestone'
+ click_button 'Add new task'
+ click_button 'Add new milestone'
name = find('.fields .fields input[id$=name]')[:name]
name.should match(/\Aproject\[tasks_attributes\]\[\d+\]\[milestones_attributes\]\[\d+\]\[name\]\z/)
end
it 'generates correct name for the nested input (has_one => has_many)', :js => true do
visit '/companies/new?type=jquery'
- click_link 'Add new task'
+ click_button 'Add new task'
name = find('.fields .fields input[id$=name]')[:name]
name.should match(/\Acompany\[project_attributes\]\[tasks_attributes\]\[\d+\]\[name\]\z/)
end
it 'generates correct name for the nested input (has_one => has_many => has_many)', :js => true do
visit '/companies/new?type=jquery'
- click_link 'Add new task'
- click_link 'Add new milestone'
+ click_button 'Add new task'
+ click_button 'Add new milestone'
name = find('.fields .fields .fields input[id$=name]')[:name]
name.should match(/\Acompany\[project_attributes\]\[tasks_attributes\]\[\d+\]\[milestones_attributes\]\[\d+\]\[name\]\z/)
end
diff --git a/spec/nested_form/builder_spec.rb b/spec/nested_form/builder_spec.rb
index 22bdde0d..ed968a0d 100644
--- a/spec/nested_form/builder_spec.rb
+++ b/spec/nested_form/builder_spec.rb
@@ -17,46 +17,46 @@
builder.new(:item, project, template, {}, proc {})
end
- describe '#link_to_add' do
- it "behaves similar to a Rails link_to" do
- subject.link_to_add("Add", :tasks).should == 'Add'
- subject.link_to_add("Add", :tasks, :class => "foo", :href => "url").should == 'Add'
- subject.link_to_add(:tasks) { "Add" }.should == 'Add'
+ describe '#button_to_add' do
+ it "behaves similar to a Rails button_to" do
+ subject.button_to_add("Add", :tasks).should == ''
+ subject.button_to_add("Add", :tasks, :class => "foo").should == ''
+ subject.button_to_add(:tasks) { "Add" }.should == ''
end
it 'raises ArgumentError when missing association is provided' do
expect {
- subject.link_to_add('Add', :bugs)
+ subject.button_to_add('Add', :bugs)
}.to raise_error(ArgumentError)
end
it 'raises ArgumentError when accepts_nested_attributes_for is missing' do
expect {
- subject.link_to_add('Add', :not_nested_tasks)
+ subject.button_to_add('Add', :not_nested_tasks)
}.to raise_error(ArgumentError)
end
end
- describe '#link_to_remove' do
- it "behaves similar to a Rails link_to" do
- subject.link_to_remove("Remove").should == 'Remove'
- subject.link_to_remove("Remove", :class => "foo", :href => "url").should == 'Remove'
- subject.link_to_remove { "Remove" }.should == 'Remove'
+ describe '#button_to_remove' do
+ it "behaves similar to a Rails button_to" do
+ subject.button_to_remove("Remove").should == ''
+ subject.button_to_remove("Remove", :class => "foo").should == ''
+ subject.button_to_remove { "Remove" }.should == ''
end
it 'has data-association attribute' do
project.tasks.build
subject.fields_for(:tasks, :builder => builder) do |tf|
- tf.link_to_remove 'Remove'
- end.should match 'Remove'
+ tf.button_to_remove 'Remove'
+ end.should match 'Remove'
end
context 'when association is declared in a model by the class_name' do
it 'properly detects association name' do
project.assignments.build
subject.fields_for(:assignments, :builder => builder) do |tf|
- tf.link_to_remove 'Remove'
- end.should match 'Remove'
+ tf.button_to_remove 'Remove'
+ end.should match 'Remove'
end
end
@@ -66,9 +66,9 @@
task.milestones.build
subject.fields_for(:tasks, :builder => builder) do |tf|
tf.fields_for(:milestones, :builder => builder) do |mf|
- mf.link_to_remove 'Remove'
+ mf.button_to_remove 'Remove'
end
- end.should match 'Remove'
+ end.should match 'Remove'
end
end
end
@@ -98,7 +98,7 @@
task = project.tasks.build
task.mark_for_destruction
subject.fields_for(:tasks) { 'Task' }
- subject.link_to_add('Add', :tasks)
+ subject.button_to_add('Add', :tasks)
output = template.send(:after_nested_form_callbacks)
expected = ERB::Util.html_escape '