diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 00000000..64424809
Binary files /dev/null and b/.DS_Store differ
diff --git a/.rvmrc b/.rvmrc
deleted file mode 100644
index 3f63e3a7..00000000
--- a/.rvmrc
+++ /dev/null
@@ -1 +0,0 @@
-rvm use 1.9.2@nested_form --create
diff --git a/Gemfile b/Gemfile
index f5191458..d2aa28b0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,3 +3,4 @@ gemspec :path => '.'
instance_eval File.read(File.expand_path('../gemfiles/Gemfile.base', __FILE__))
gem 'rails', '~> 3.2.0'
+gem 'test-unit'
\ No newline at end of file
diff --git a/Rakefile b/Rakefile
index 93920dda..3548596d 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,6 +1,13 @@
require 'rubygems'
require 'rake'
+module TempFixForRakeLastComment
+ def last_comment
+ last_description
+ end
+end
+Rake::Application.send :include, TempFixForRakeLastComment
+
begin
require 'rspec/core/rake_task'
desc "Run RSpec"
@@ -24,11 +31,11 @@ namespace :spec do
desc 'Install gems from additional gemfiles'
task :install do
system 'bundle install'
- ENV.delete('GEM_HOME')
- ENV['BUNDLE_GEMFILE'] = File.expand_path('../gemfiles/Gemfile.rails3_1', __FILE__)
- system 'bundle install'
- ENV['BUNDLE_GEMFILE'] = File.expand_path('../gemfiles/Gemfile.rails3_0', __FILE__)
- system 'bundle install'
+ # ENV.delete('GEM_HOME')
+ # ENV['BUNDLE_GEMFILE'] = File.expand_path('../gemfiles/Gemfile.rails3_1', __FILE__)
+ # system 'bundle install'
+ # ENV['BUNDLE_GEMFILE'] = File.expand_path('../gemfiles/Gemfile.rails3_0', __FILE__)
+ # system 'bundle install'
end
desc 'Run tests with Rails 3.1.x'
@@ -47,7 +54,7 @@ namespace :spec do
task :all do
Rake::Task["spec"].execute
- Rake::Task["spec:rails3_1"].execute
- Rake::Task["spec:rails3_0"].execute
+ # Rake::Task["spec:rails3_1"].execute
+ # Rake::Task["spec:rails3_0"].execute
end
end
diff --git a/gemfiles/Gemfile.rails3_0 b/gemfiles/Gemfile.rails3_0
deleted file mode 100644
index 89368140..00000000
--- a/gemfiles/Gemfile.rails3_0
+++ /dev/null
@@ -1,5 +0,0 @@
-gemspec :path => '../'
-instance_eval File.read(File.expand_path('../Gemfile.base', __FILE__))
-# forcing 3.0.20 (rather than 3.0.0) fixes a bug where bundle hangs
-# trying to fetch gems from github
-gem "rails", "~> 3.0.20"
diff --git a/gemfiles/Gemfile.rails3_1 b/gemfiles/Gemfile.rails3_2
similarity index 79%
rename from gemfiles/Gemfile.rails3_1
rename to gemfiles/Gemfile.rails3_2
index 3b5f9faa..334591d8 100644
--- a/gemfiles/Gemfile.rails3_1
+++ b/gemfiles/Gemfile.rails3_2
@@ -1,3 +1,3 @@
gemspec :path => '../'
instance_eval File.read(File.expand_path('../Gemfile.base', __FILE__))
-gem "rails", "~> 3.1.0"
+gem "rails", "~> 3.2.0"
diff --git a/spec/.DS_Store b/spec/.DS_Store
new file mode 100644
index 00000000..50abe249
Binary files /dev/null and b/spec/.DS_Store differ
diff --git a/spec/dummy/.DS_Store b/spec/dummy/.DS_Store
new file mode 100644
index 00000000..c32d382d
Binary files /dev/null and b/spec/dummy/.DS_Store differ
diff --git a/spec/dummy/app/.DS_Store b/spec/dummy/app/.DS_Store
new file mode 100644
index 00000000..650ce685
Binary files /dev/null and b/spec/dummy/app/.DS_Store differ
diff --git a/spec/dummy/app/assets/.DS_Store b/spec/dummy/app/assets/.DS_Store
new file mode 100644
index 00000000..f3027350
Binary files /dev/null and b/spec/dummy/app/assets/.DS_Store differ
diff --git a/spec/dummy/app/assets/javascripts/application.js b/spec/dummy/app/assets/javascripts/application.js
old mode 100644
new mode 100755
diff --git a/spec/dummy/app/assets/javascripts/jquery.js b/spec/dummy/app/assets/javascripts/jquery.js
old mode 100644
new mode 100755
diff --git a/spec/dummy/app/assets/javascripts/jquery_events_test.js b/spec/dummy/app/assets/javascripts/jquery_events_test.js
old mode 100644
new mode 100755
diff --git a/spec/dummy/app/assets/javascripts/projects.js b/spec/dummy/app/assets/javascripts/projects.js
old mode 100644
new mode 100755
diff --git a/spec/dummy/app/assets/javascripts/prototype.js b/spec/dummy/app/assets/javascripts/prototype.js
old mode 100644
new mode 100755
diff --git a/spec/dummy/app/assets/javascripts/prototype_events_test.js b/spec/dummy/app/assets/javascripts/prototype_events_test.js
old mode 100644
new mode 100755
diff --git a/spec/dummy/app/views/projects/with_target_links.html.erb b/spec/dummy/app/views/projects/with_target_links.html.erb
new file mode 100644
index 00000000..e9e868ab
--- /dev/null
+++ b/spec/dummy/app/views/projects/with_target_links.html.erb
@@ -0,0 +1,17 @@
+<%= nested_form_for Project.new do |f| -%>
+ <%= f.text_field :name %>
+
+ <%= f.fields_for :tasks do |tf| -%>
+ <%= tf.text_field :name %>
+
+ <%= tf.fields_for :milestones do |mf| %>
+ <%= mf.text_field :name %>
+ <%= mf.link_to_remove 'Remove milestone' %>
+ <% end %>
+
+ <%= tf.link_to_add 'Add new milestone', :milestones, data: {target: '#milestone-fields'} %>
+ <%= tf.link_to_remove 'Remove' %>
+ <% end -%>
+
+ <%= f.link_to_add 'Add new task', :tasks, data: {target: '#task-fields'} %>
+<% end -%>
diff --git a/spec/form_spec.rb b/spec/form_spec.rb
index 2701051b..89ee69d7 100644
--- a/spec/form_spec.rb
+++ b/spec/form_spec.rb
@@ -40,6 +40,17 @@ def check_form
inputs.first[:name].should_not eq(inputs.last[:name])
end
+ it 'works when specify target', :js => true do
+ visit '/projects/with_target_links'
+ click_link 'Add new task'
+ click_link 'Remove'
+ click_link 'Add new task'
+ click_link 'Add new milestone'
+
+ # page.should have_selector('#milestone-fields .fields', :visible => true)
+ find(:css, "#milestone-fields .fields").should be_visible
+ end
+
it 'generates correct name for the nested input', :js => true do
visit '/projects/new?type=jquery'
click_link 'Add new task'
diff --git a/vendor/assets/javascripts/jquery_nested_form.js b/vendor/assets/javascripts/jquery_nested_form.js
index b9225b14..4445c5e8 100644
--- a/vendor/assets/javascripts/jquery_nested_form.js
+++ b/vendor/assets/javascripts/jquery_nested_form.js
@@ -16,37 +16,15 @@
// of each of the parent objects
var context = ($(link).closest('.fields').closestChild('input, textarea, select').eq(0).attr('name') || '').replace(/\[[a-z_]+\]$/, '');
- // If the parent has no inputs we need to strip off the last pair
- var current = content.match(new RegExp('\\[([a-z_]+)\\]\\[new_' + assoc + '\\]'))[1];
- if (current) {
- context = context.replace(new RegExp('\\['+current+'\\]\\[(new_)?\\d+\\]$'), '');
- }
-
- // context will be something like this for a brand new form:
- // project[tasks_attributes][1255929127459][assignments_attributes][1255929128105]
- // or for an edit form:
- // project[tasks_attributes][0][assignments_attributes][1]
- if (context) {
- var parentNames = context.match(/[a-z_]+_attributes(?=\]\[(new_)?\d+\])/g) || [];
- var parentIds = context.match(/[0-9]+/g) || [];
+ if (context){
+ var parentNames = context.match(/[a-z_]+_attributes(?=\]\[(new_)?.+\])/g) || [];
+ var parentIds = context.match(/[0-9]+/g) || [];
- for(var i = 0; i < parentNames.length; i++) {
- if(parentIds[i]) {
- content = content.replace(
- new RegExp('(_' + parentNames[i] + ')_.+?_', 'g'),
- '$1_' + parentIds[i] + '_');
-
- content = content.replace(
- new RegExp('(\\[' + parentNames[i] + '\\])\\[.+?\\]', 'g'),
- '$1[' + parentIds[i] + ']');
- }
- }
+ content = this.replaceContentFromParents(content, assoc, parentNames, parentIds)
+ }
+ else{
+ content = this.replaceContentFromParents(content, assoc)
}
-
- // Make a unique ID for the new child
- var regexp = new RegExp('new_' + assoc, 'g');
- var new_id = this.newId();
- content = $.trim(content.replace(regexp, new_id));
var field = this.insertFields(content, assoc, link);
// bubble up event upto document (through form)
@@ -60,8 +38,12 @@
},
insertFields: function(content, assoc, link) {
var target = $(link).data('target');
- if (target) {
- return $(content).appendTo($(target));
+ if (target) {
+ if($(link).closest('.fields').length > 0) {
+ return $(content).appendTo($(link).closest('.fields').find($(link).data('target')));
+ } else {
+ return $(content).appendTo($(target));
+ }
} else {
return $(content).insertBefore(link);
}
@@ -80,6 +62,36 @@
.trigger({ type: 'nested:fieldRemoved', field: field })
.trigger({ type: 'nested:fieldRemoved:' + assoc, field: field });
return false;
+ },
+ replaceContentFromParents: function(content, assoc, parentNames, parentIds){
+ parentNames = parentNames || [];
+ parentIds = parentIds || [];
+
+ if (parentNames.length > 0 && parentNames.length == parentIds.length){
+ // we need to get a name pattern and id pattern that is mapped to parent
+ var fullNameRegexp = ""; // regexp used to find the full name pattern in blueprint
+ var fullIdRegexp = ""; // regexp used to find the full id pattern in blueprint
+ var fullNameReplace = ""; // name part from parents, eg. [parameters_attributes][0][children_attributes][1]
+ var fullIdReplace = ""; // id part from parents, eg. _parameters_attributes_0_children_attributes_1
+ for (var i=0; i< parentNames.length; i++){
+ fullNameRegexp += "\\[" + parentNames[i] + "\\]\\[.+?\\]";
+ fullNameReplace += "[" + parentNames[i] + "][" + parentIds[i] + "]";
+ fullIdRegexp += "_" + parentNames[i] + "_.+?";
+ fullIdReplace += "_" + parentNames[i] + "_" + parentIds[i];
+
+ if (i== parentNames.length -1){
+ fullIdRegexp += "(?=_" + assoc + "_attributes)"
+ }
+ }
+ content = content.replace(new RegExp(fullNameRegexp, 'g'), fullNameReplace);
+ content = content.replace(new RegExp(fullIdRegexp, 'g'), fullIdReplace);
+ }
+
+ // Make a unique ID for the new child
+ var regexp = new RegExp('new_' + assoc, 'g');
+ var new_id = this.newId();
+ content = $.trim(content.replace(regexp, new_id));
+ return content;
}
};