nested_form 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +16 -0
- data/README.rdoc +20 -19
- data/lib/generators/nested_form/install_generator.rb +1 -1
- data/lib/generators/nested_form/templates/jquery_nested_form.js +39 -37
- data/lib/generators/nested_form/templates/prototype_nested_form.js +3 -3
- data/lib/nested_form/builder.rb +6 -4
- data/lib/nested_form/view_helper.rb +1 -1
- data/spec/spec_helper.rb +3 -3
- metadata +3 -2
data/CHANGELOG.rdoc
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
0.1.0 (March 26, 2011)
|
2
|
+
|
3
|
+
* Prefix new records with "new_" so there's no possible conflict with existing records - issue #21
|
4
|
+
|
5
|
+
* Add support for _fields partial if no block is passed in to fields_for
|
6
|
+
|
7
|
+
* Use the $-jquery-function only inside the jQuery scope (thanks nhocki)
|
8
|
+
|
9
|
+
* Triggers nested:fieldAdded and nested:fieldRemoved events (thanks pirelenito)
|
10
|
+
|
11
|
+
* Fixed JavaScript bug for nested attributes in has_one association (thanks pirelenito)
|
12
|
+
|
13
|
+
|
14
|
+
0.0.0 (February 17, 2011)
|
15
|
+
|
16
|
+
* Initial release
|
data/README.rdoc
CHANGED
@@ -1,44 +1,38 @@
|
|
1
1
|
= Nested Form
|
2
2
|
|
3
|
-
|
3
|
+
This is a Rails gem for conveniently manage multiple nested models in a single form. It does so in an unobtrusive way through jQuery or Prototype.
|
4
4
|
|
5
|
-
|
5
|
+
This gem only works with Rails 3. See the {rails2 branch}[https://github.com/ryanb/nested_form/tree/rails2] for a plugin to work in Rails 2.
|
6
6
|
|
7
7
|
|
8
|
-
==
|
8
|
+
== Setup
|
9
9
|
|
10
|
-
Add it to your Gemfile
|
11
|
-
|
12
|
-
gem "nested_form"
|
10
|
+
Add it to your Gemfile then run +bundle+ to install it.
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
bundle install
|
12
|
+
gem "nested_form"
|
17
13
|
|
18
|
-
|
14
|
+
Next run the generator to create the JavaScript file. This will automatically detect if you are using jQuery or Prototype.
|
19
15
|
|
20
|
-
rails
|
16
|
+
rails g nested_form:install
|
21
17
|
|
18
|
+
Running the generator will add a file at <tt>public/javascripts/nested_form.js</tt> which should be included after the jQuery or Prototype framework.
|
22
19
|
|
23
|
-
|
20
|
+
<%= javascript_include_tag :defaults, "nested_form" %>
|
24
21
|
|
25
|
-
Running the generator will add a file at public/javascripts/nested_form.js which should be included after the jQuery or Prototype framework.
|
26
22
|
|
27
|
-
|
23
|
+
== Usage
|
28
24
|
|
29
|
-
|
25
|
+
Use the +nested_form_for+ helper method to enable the nesting.
|
30
26
|
|
31
27
|
<%= nested_form_for @project do |f| %>
|
32
28
|
|
33
|
-
|
29
|
+
You will then be able to use +link_to_add+ and +link_to_remove+ helper methods on the form builder in combination with fields_for to dynamically add/remove nested records.
|
34
30
|
|
35
31
|
<%= f.fields_for :tasks do |task_form| %>
|
36
32
|
<%= task_form.text_field :name %>
|
37
33
|
<%= task_form.link_to_remove "Remove this task" %>
|
38
34
|
<% end %>
|
39
|
-
|
40
|
-
|
41
|
-
This generates links which dynamically add and remove fields.
|
35
|
+
<p><%= f.link_to_add "Add a task", :tasks %></p>
|
42
36
|
|
43
37
|
|
44
38
|
== Partials
|
@@ -50,8 +44,15 @@ It is often desirable to move the nested fields into a partial to keep things or
|
|
50
44
|
In this case it will look for a partial called "task_fields" and pass the form builder as an f variable to it.
|
51
45
|
|
52
46
|
|
47
|
+
== Events
|
48
|
+
|
49
|
+
If you are using jQuery, <tt>nested:fieldAdded<tt> and <tt>nested:fieldRemoved</tt> events are triggered on the +form+ element after adding and removing fields.
|
50
|
+
|
51
|
+
|
53
52
|
== Special Thanks
|
54
53
|
|
55
54
|
This gem was originally based on the solution by Tim Riley in his {complex-form-examples fork}[https://github.com/timriley/complex-form-examples/tree/unobtrusive-jquery-deep-fix2].
|
56
55
|
|
57
56
|
Thank you Andrew Manshin for the Rails 3 transition, {Andrea Singh}[https://github.com/madebydna] for converting to a gem and {Peter Giacomo Lombardo}[https://github.com/pglombardo] for Prototype support.
|
57
|
+
|
58
|
+
Andrea also wrote a great {blog post}[http://blog.madebydna.com/all/code/2010/10/07/dynamic-nested-froms-with-the-nested-form-gem.html] on the internal workings of this gem.
|
@@ -1,46 +1,48 @@
|
|
1
|
-
|
2
|
-
$('form a.add_nested_fields').live('click', function() {
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
jQuery(function($) {
|
2
|
+
$('form a.add_nested_fields').live('click', function() {
|
3
|
+
// Setup
|
4
|
+
var assoc = $(this).attr('data-association'); // Name of child
|
5
|
+
var content = $('#' + assoc + '_fields_blueprint').html(); // Fields template
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
// Make the context correct by replacing new_<parents> with the generated ID
|
8
|
+
// of each of the parent objects
|
9
|
+
var context = ($(this).closest('.fields').find('input:first').attr('name') || '').replace(new RegExp('\[[a-z]+\]$'), '');
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
// context will be something like this for a brand new form:
|
12
|
+
// project[tasks_attributes][new_1255929127459][assignments_attributes][new_1255929128105]
|
13
|
+
// or for an edit form:
|
14
|
+
// project[tasks_attributes][0][assignments_attributes][1]
|
15
|
+
if(context) {
|
16
|
+
var parent_names = context.match(/[a-z_]+_attributes/g) || [];
|
17
|
+
var parent_ids = context.match(/(new_)?[0-9]+/g) || [];
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
for(i = 0; i < parent_names.length; i++) {
|
20
|
+
if(parent_ids[i]) {
|
21
|
+
content = content.replace(
|
22
|
+
new RegExp('(\\[' + parent_names[i] + '\\])\\[.+?\\]', 'g'),
|
23
|
+
'$1[' + parent_ids[i] + ']'
|
24
|
+
)
|
25
|
+
}
|
25
26
|
}
|
26
27
|
}
|
27
|
-
}
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
// Make a unique ID for the new child
|
30
|
+
var regexp = new RegExp('new_' + assoc, 'g');
|
31
|
+
var new_id = new Date().getTime();
|
32
|
+
content = content.replace(regexp, "new_" + new_id);
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
$(this).before(content);
|
35
|
+
$(this).closest("form").trigger('nested:fieldAdded');
|
36
|
+
return false;
|
37
|
+
});
|
37
38
|
|
38
|
-
$('form a.remove_nested_fields').live('click', function() {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
$('form a.remove_nested_fields').live('click', function() {
|
40
|
+
var hidden_field = $(this).prev('input[type=hidden]')[0];
|
41
|
+
if(hidden_field) {
|
42
|
+
hidden_field.value = '1';
|
43
|
+
}
|
44
|
+
$(this).closest('.fields').hide();
|
45
|
+
$(this).closest("form").trigger('nested:fieldRemoved');
|
46
|
+
return false;
|
47
|
+
});
|
45
48
|
});
|
46
|
-
});
|
@@ -9,12 +9,12 @@ document.observe('click', function(e, el) {
|
|
9
9
|
var context = (el.getOffsetParent('.fields').firstDescendant().readAttribute('name') || '').replace(new RegExp('\[[a-z]+\]$'), '');
|
10
10
|
|
11
11
|
// context will be something like this for a brand new form:
|
12
|
-
// project[tasks_attributes][
|
12
|
+
// project[tasks_attributes][new_1255929127459][assignments_attributes][new_1255929128105]
|
13
13
|
// or for an edit form:
|
14
14
|
// project[tasks_attributes][0][assignments_attributes][1]
|
15
15
|
if(context) {
|
16
16
|
var parent_names = context.match(/[a-z_]+_attributes/g) || [];
|
17
|
-
var parent_ids = context.match(/[0-9]+/g);
|
17
|
+
var parent_ids = context.match(/(new_)?[0-9]+/g) || [];
|
18
18
|
|
19
19
|
for(i = 0; i < parent_names.length; i++) {
|
20
20
|
if(parent_ids[i]) {
|
@@ -29,7 +29,7 @@ document.observe('click', function(e, el) {
|
|
29
29
|
// Make a unique ID for the new child
|
30
30
|
var regexp = new RegExp('new_' + assoc, 'g');
|
31
31
|
var new_id = new Date().getTime();
|
32
|
-
content = content.replace(regexp, new_id);
|
32
|
+
content = content.replace(regexp, "new_" + new_id);
|
33
33
|
|
34
34
|
el.insert({ before: content });
|
35
35
|
return false;
|
data/lib/nested_form/builder.rb
CHANGED
@@ -16,13 +16,15 @@ module NestedForm
|
|
16
16
|
hidden_field(:_destroy) + @template.link_to(name, "javascript:void(0)", :class => "remove_nested_fields")
|
17
17
|
end
|
18
18
|
|
19
|
-
def fields_for_with_nested_attributes(
|
19
|
+
def fields_for_with_nested_attributes(association_name, args, block)
|
20
|
+
# TODO Test this better
|
21
|
+
block ||= Proc.new { |fields| @template.render(:partial => "#{association_name.to_s.singularize}_fields", :locals => {:f => fields}) }
|
20
22
|
@fields ||= {}
|
21
|
-
@fields[
|
22
|
-
super
|
23
|
+
@fields[association_name] = block
|
24
|
+
super(association_name, args, block)
|
23
25
|
end
|
24
26
|
|
25
|
-
def fields_for_nested_model(name,
|
27
|
+
def fields_for_nested_model(name, object, options, block)
|
26
28
|
output = '<div class="fields">'.html_safe
|
27
29
|
output << super
|
28
30
|
output.safe_concat('</div>')
|
data/spec/spec_helper.rb
CHANGED
@@ -22,15 +22,15 @@ end
|
|
22
22
|
|
23
23
|
class TablelessModel < ActiveRecord::Base
|
24
24
|
def self.columns() @columns ||= []; end
|
25
|
-
|
25
|
+
|
26
26
|
def self.column(name, sql_type = nil, default = nil, null = true)
|
27
27
|
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def self.quoted_table_name
|
31
31
|
name.pluralize.underscore
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def quoted_id
|
35
35
|
"0"
|
36
36
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: nested_form
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.1.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Ryan Bates
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2011-
|
14
|
+
date: 2011-03-26 00:00:00 -07:00
|
15
15
|
default_executable:
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
@@ -65,6 +65,7 @@ files:
|
|
65
65
|
- spec/nested_form/builder_spec.rb
|
66
66
|
- spec/nested_form/view_helper_spec.rb
|
67
67
|
- spec/spec_helper.rb
|
68
|
+
- CHANGELOG.rdoc
|
68
69
|
- Gemfile
|
69
70
|
- LICENSE
|
70
71
|
- Rakefile
|