nested_editor_for 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/README.md +36 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/nested_editor_for/builder.rb +129 -0
- data/lib/nested_editor_for/engine.rb +5 -0
- data/lib/nested_editor_for/version.rb +3 -0
- data/lib/nested_editor_for.rb +6 -0
- data/nested_editor_for.gemspec +22 -0
- data/vendor/assets/javascripts/nested_editor_for.js +225 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ca3f776538ef3cac0f158b79dcb420d84a222383
|
4
|
+
data.tar.gz: 09f9a2c066e686e94a6352a2b370e10e7541077a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1c9ac93bf8cfe6b1be98e279871291910d61f0e2eaa8d957e237255b070efbfbd31acdbd8599fbf6a7c535c502cbd9499226ee43acdd9c5a557ec421505deec0
|
7
|
+
data.tar.gz: e1f6df80b5919a2d832e3ff82521dfbf94a224e609227f58edeb04a935a6459b1c16e61a7f2f90141b3b5a67f9d634cc41e95fd7b0310c65b5847c7766e5801e
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# NestedEditorFor
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/nested_editor_for`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'nested_editor_for'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install nested_editor_for
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/nested_editor_for.
|
36
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "nested_editor_for"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
module NestedEditorFor
|
2
|
+
module Builder
|
3
|
+
attr_reader :object, :template
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
# override: do arrays like attributes
|
8
|
+
def fields_for(method_or_object, *args, &block)
|
9
|
+
options = args.extract_options!
|
10
|
+
if @object
|
11
|
+
case method_or_object
|
12
|
+
when String, Symbol
|
13
|
+
object = @object.send method_or_object
|
14
|
+
if object.is_a?(Array) or object.is_a?(ActiveRecord::Relation)
|
15
|
+
name = options[:name] || "#{@object_name}[#{method_or_object}_attributes]"
|
16
|
+
return ((0...object.length).collect do |i|
|
17
|
+
template.fields_for("#{name}[#{i}]", object[i], *args, &block)
|
18
|
+
end).join.html_safe
|
19
|
+
else
|
20
|
+
name = options[:name] || method_or_object
|
21
|
+
return super(name, object, *args, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
super(method_or_object, *args, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
def hidden_field(method_or_object, *args)
|
32
|
+
method = case method_or_object
|
33
|
+
when String, Symbol; method_or_object
|
34
|
+
when Array; obj.first.class.name.tableize.singularize
|
35
|
+
else; obj.class.name.tableize.singularize
|
36
|
+
end
|
37
|
+
|
38
|
+
html_options = args.extract_options!
|
39
|
+
html_options[:id] = html_options[:name].parameterize.underscore if html_options[:name] && !html_options.key?(:id)
|
40
|
+
html_options["data-attr"] = method
|
41
|
+
|
42
|
+
super(method_or_object, html_options)
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
def static_field(method, value)
|
48
|
+
attr_name = "#{@object_name}[#{method}]"
|
49
|
+
html_options = {
|
50
|
+
'data-attr' => method,
|
51
|
+
:type => "hidden",
|
52
|
+
:value => value,
|
53
|
+
:attr => attr_name,
|
54
|
+
:name => attr_name
|
55
|
+
}
|
56
|
+
template.tag("input", html_options)
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
def nested_editor_for(method, *args, &block)
|
62
|
+
raise ArgumentError, "Missing block" unless block_given?
|
63
|
+
|
64
|
+
template.instance_variable_set "@enable_nested_records", true
|
65
|
+
|
66
|
+
attr_name = "#{@object_name}[#{method}_attributes]"
|
67
|
+
|
68
|
+
# for some reason, things break if I make "#{@object_name}[#{object_name.to_s}_attributes]" the 'id' of the table
|
69
|
+
template.content_tag(:div, class: "nested editor") do
|
70
|
+
template.content_tag(:ol, attr: attr_name) do
|
71
|
+
nested_editor_wrapper(method, attr_name, &block)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
def nested_editor_wrapper(method, attr_name, &block)
|
83
|
+
i = -1
|
84
|
+
fields_for(method, name: attr_name) do |f|
|
85
|
+
i += 1
|
86
|
+
nested_editor_row(f, attr_name, i, method, &block)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def nested_editor_row(f, attr_name, i, method, &block)
|
91
|
+
singular = method.to_s.singularize
|
92
|
+
attr_name = "#{attr_name}[#{i}]".html_safe # for sake of EditorBuilder which wants to pass "'+i+'"
|
93
|
+
html_options = {
|
94
|
+
class: "nested-row #{singular}",
|
95
|
+
:id => "#{singular}_#{i}".html_safe, # for sake of EditorBuilder which wants to pass "'+i+'"
|
96
|
+
:name => attr_name,
|
97
|
+
:attr => attr_name
|
98
|
+
}
|
99
|
+
template.content_tag(:li, html_options) do
|
100
|
+
nested_row_hidden_properties(f) <<
|
101
|
+
template.capture(f, &block) <<
|
102
|
+
delete_nested_command <<
|
103
|
+
add_nested_command
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def nested_row_hidden_properties(f)
|
108
|
+
template.content_tag(:div, class: "hidden") do
|
109
|
+
(f.hidden_field :id) <<
|
110
|
+
(f.static_field :_destroy, (f.object.respond_to?(:_destroy) && f.object._destroy) ? 1 : 0)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def delete_nested_command
|
115
|
+
template.content_tag(:span, class: "delete-nested") do
|
116
|
+
"<a class=\"delete-link delete-nested-link\" href=\"#\" title=\"Delete\">Delete</a>".html_safe
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_nested_command
|
121
|
+
template.content_tag(:span, class: "add-nested") do
|
122
|
+
"<a class=\"add-link add-nested-link\" href=\"#\" title=\"Add\">Add</a>".html_safe
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nested_editor_for/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "nested_editor_for"
|
8
|
+
spec.version = NestedEditorFor::VERSION
|
9
|
+
spec.authors = ["Bob Lail"]
|
10
|
+
spec.email = ["bob.lailfamily@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Extends FormBuilder to support editing child records}
|
13
|
+
spec.homepage = "https://github.com/boblail/nested_editor_for"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
|
+
spec.bindir = "exe"
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
21
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
22
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
(function () {
|
2
|
+
|
3
|
+
function enableNestedEditors() {
|
4
|
+
enableNestedEditorsIn(document.body);
|
5
|
+
}
|
6
|
+
|
7
|
+
function enableNestedEditorsIn(parent) {
|
8
|
+
withEach(findNestedEditors(parent), initializeNestedEditor);
|
9
|
+
}
|
10
|
+
|
11
|
+
function updateNestedEditors() {
|
12
|
+
updateNestedEditorsIn(document.body);
|
13
|
+
}
|
14
|
+
|
15
|
+
function updateNestedEditorsIn(parent) {
|
16
|
+
withEach(findNestedEditors(parent), updateNestedEditor);
|
17
|
+
}
|
18
|
+
|
19
|
+
function findNestedEditors(parent) {
|
20
|
+
return $(parent).find('.nested.editor');
|
21
|
+
}
|
22
|
+
|
23
|
+
function initializeNestedEditor(nested_editor) {
|
24
|
+
$(nested_editor).on('click', '.add-nested-link', nestedRowAction(addNestedRow));
|
25
|
+
$(nested_editor).on('click', '.delete-nested-link', nestedRowAction(deleteNestedRow));
|
26
|
+
updateNestedEditor(nested_editor);
|
27
|
+
|
28
|
+
// Hide rows that were created with _destroy="1"
|
29
|
+
var deleted_rows = $(nested_editor).find('[data-attr="_destroy"][value="1"]');
|
30
|
+
for(var i=0, ii=deleted_rows.length, row, input; i<ii; i++) {
|
31
|
+
input = deleted_rows[i];
|
32
|
+
row = $(input).closest('.nested-row')[0];
|
33
|
+
row && $(row).hide();
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
function nestedRowAction(action) {
|
38
|
+
return function(e) {
|
39
|
+
e.preventDefault();
|
40
|
+
e.stopPropagation();
|
41
|
+
var row = getNestedRowFromEvent(e);
|
42
|
+
row && action(row);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
function getNestedRowFromEvent(e) {
|
47
|
+
var row = $(e.target).closest('.nested-row')[0];
|
48
|
+
row || FT.debug('[getParentNestedRow] .nested-row not found');
|
49
|
+
return row;
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
function addNestedRow(row) {
|
55
|
+
if(!row.parentNode) {return;}
|
56
|
+
var nested_editor = $(row).closest('.nested.editor')[0];
|
57
|
+
|
58
|
+
// Clone a row
|
59
|
+
var new_row = $(row).clone()[0],
|
60
|
+
name = $(new_row).attr('name').replace(/\[(\d+)\]/, function(m, n){return '['+(Number(n)+1)+']';});
|
61
|
+
new_row.id = row.id.replace(/(\d+)$/, function(m, n){return Number(n) + 1;});
|
62
|
+
$(new_row).attr('name', name);
|
63
|
+
$(new_row).attr('attr', name);
|
64
|
+
row.parentNode.appendChild(new_row);
|
65
|
+
|
66
|
+
// Reset the cloned row's values
|
67
|
+
setNestedRowFieldValue(new_row, '_destroy', 0);
|
68
|
+
setNestedRowFieldValue(new_row, 'id', '');
|
69
|
+
resetFormFieldsIn(new_row);
|
70
|
+
selectFirstFieldIn(new_row);
|
71
|
+
|
72
|
+
// observer.fire('after_add_nested', [nested_editor, new_row]);
|
73
|
+
updateNestedEditor(nested_editor);
|
74
|
+
}
|
75
|
+
|
76
|
+
function deleteNestedRow(row) {
|
77
|
+
if(!row.parentNode) {return;}
|
78
|
+
var nested_editor = $(row).closest('.nested.editor')[0];
|
79
|
+
|
80
|
+
// How many undeleted records are left? Only 1? Create a new empty record.
|
81
|
+
var undeleted_rows = 0;
|
82
|
+
withEach(row.parentNode.childNodes, function(row) {
|
83
|
+
(getNestedRowFieldValue(row, '_destroy') != '1') && (undeleted_rows++);
|
84
|
+
});
|
85
|
+
(undeleted_rows <= 1) && addNestedRow(row);
|
86
|
+
|
87
|
+
// Give focus either to the previous row or the next row
|
88
|
+
var previous_row = $(row).prev()[0] || $(row).next()[0];
|
89
|
+
selectFirstFieldIn(previous_row);
|
90
|
+
|
91
|
+
// Remove or hide the deleted record
|
92
|
+
if(getNestedRowFieldValue(row, 'id')) {
|
93
|
+
setNestedRowFieldValue(row, '_destroy', 1);
|
94
|
+
$(row).hide();
|
95
|
+
} else {
|
96
|
+
row.parentNode.removeChild(row);
|
97
|
+
}
|
98
|
+
|
99
|
+
// observer.fire('after_delete_nested', [nested_editor, row]);
|
100
|
+
updateNestedEditor(nested_editor);
|
101
|
+
}
|
102
|
+
|
103
|
+
function getNestedRowFieldValue(row, attr) {
|
104
|
+
var field = getNestedRowField(row, attr);
|
105
|
+
return field && field.value;
|
106
|
+
}
|
107
|
+
|
108
|
+
function setNestedRowFieldValue(row, attr, value) {
|
109
|
+
var field = getNestedRowField(row, attr);
|
110
|
+
field && (field.value = value);
|
111
|
+
}
|
112
|
+
|
113
|
+
function getNestedRowField(row, attr) {
|
114
|
+
return $(row).find('[data-attr="' + attr + '"]')[0];
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
function updateNestedEditor(nested_editor) {
|
121
|
+
var object_name = $(nested_editor).attr('name'),
|
122
|
+
rows = $(nested_editor).find('.nested-row'),
|
123
|
+
visible_rows = [],
|
124
|
+
row;
|
125
|
+
|
126
|
+
for(var i=0, ii=rows.length; i<ii; i++) {
|
127
|
+
row = rows[i];
|
128
|
+
renumberNestedRow(row, i);
|
129
|
+
(getNestedRowFieldValue(row, '_destroy') != '1') && visible_rows.push(row);
|
130
|
+
}
|
131
|
+
|
132
|
+
var ii = visible_rows.length - 1;
|
133
|
+
for(var i=0; i<ii; i++) { setAddNestedVisibility(visible_rows[i], 'hidden'); }
|
134
|
+
if(ii >= 0) { setAddNestedVisibility(visible_rows[ii], 'visible'); }
|
135
|
+
|
136
|
+
// observer.fire('after_reset_nested', nested_editor);
|
137
|
+
}
|
138
|
+
|
139
|
+
function renumberNestedRow(row, i) {
|
140
|
+
withEach($(row).find('input, textarea, select'), function(e) {
|
141
|
+
var name = $(e).attr('name');
|
142
|
+
if(name) {
|
143
|
+
$(e).attr('name', name.replace(/\[(\d+)\]/, function() { return '[' + i + ']'; }));
|
144
|
+
}
|
145
|
+
});
|
146
|
+
}
|
147
|
+
|
148
|
+
function setAddNestedVisibility(row, add_visibility) {
|
149
|
+
var add_link = $(row).find('.add-link')[0];
|
150
|
+
add_link && $(add_link).css({visibility: add_visibility});
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
function resetNestedEditor(nested_editor) {
|
156
|
+
var nested_rows = $(nested_editor).find('.nested-row');
|
157
|
+
for(var i=1, ii=nested_rows.length; i<ii; i++) {
|
158
|
+
var row = nested_rows[i];
|
159
|
+
row.parentNode.removeChild(row);
|
160
|
+
}
|
161
|
+
updateNestedEditor(nested_editor);
|
162
|
+
}
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
function withEach(array, fn) {
|
167
|
+
for(var i=0, ii=array.length; i<ii; i++) { fn(array[i]); }
|
168
|
+
}
|
169
|
+
|
170
|
+
function member(array, item) {
|
171
|
+
for(var i=0, ii=array.length; i<ii; i++) {
|
172
|
+
if(array[i] == item) { return true; }
|
173
|
+
}
|
174
|
+
return false;
|
175
|
+
}
|
176
|
+
|
177
|
+
function resetFormFieldsIn(parent, options) {
|
178
|
+
var inputs = $(parent).find('input[type="text"], input[type="tel"], input[type="email"], textarea'),
|
179
|
+
selects = $(parent).find('select'),
|
180
|
+
nested_editors = $(parent).find('.nested.editor');
|
181
|
+
options = options || {};
|
182
|
+
|
183
|
+
function fieldToBeReset(id) {
|
184
|
+
return !(options.only && !member(options.only, input.id)) &&
|
185
|
+
!(options.except && member(options.except, input.id));
|
186
|
+
}
|
187
|
+
|
188
|
+
for(var i=0, ii=inputs.length; i<ii; i++) {
|
189
|
+
var input = inputs[i];
|
190
|
+
fieldToBeReset(input.id) && (input.value = '');
|
191
|
+
}
|
192
|
+
for(var i=0, ii=selects.length; i<ii; i++) {
|
193
|
+
var select = selects[i];
|
194
|
+
fieldToBeReset(select.id) && (select.selectedIndex = 0);
|
195
|
+
}
|
196
|
+
for(var i=0, ii=nested_editors.length; i<ii; i++) {
|
197
|
+
resetNestedEditor(nested_editors[i]);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
function selectFirstFieldIn(parent) {
|
202
|
+
var inputs = $(parent).find('input, select, textarea');
|
203
|
+
for(var i=0, ii=inputs.length; i<ii; i++) {
|
204
|
+
var input = inputs[i];
|
205
|
+
if($(input).is(':visible') && (input.type != 'hidden')) {
|
206
|
+
$(input).focus();
|
207
|
+
return;
|
208
|
+
}
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
|
213
|
+
|
214
|
+
window.NestedEditorFor = {
|
215
|
+
init: enableNestedEditors,
|
216
|
+
enableAll: enableNestedEditors,
|
217
|
+
enableIn: enableNestedEditorsIn,
|
218
|
+
updateAll: updateNestedEditors,
|
219
|
+
updateIn: updateNestedEditorsIn,
|
220
|
+
|
221
|
+
addRow: addNestedRow,
|
222
|
+
deleteRow: deleteNestedRow,
|
223
|
+
getRowFromEvent: getNestedRowFromEvent
|
224
|
+
};
|
225
|
+
})();
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nested_editor_for
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bob Lail
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- bob.lailfamily@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- ".travis.yml"
|
50
|
+
- Gemfile
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- bin/console
|
54
|
+
- bin/setup
|
55
|
+
- lib/nested_editor_for.rb
|
56
|
+
- lib/nested_editor_for/builder.rb
|
57
|
+
- lib/nested_editor_for/engine.rb
|
58
|
+
- lib/nested_editor_for/version.rb
|
59
|
+
- nested_editor_for.gemspec
|
60
|
+
- vendor/assets/javascripts/nested_editor_for.js
|
61
|
+
homepage: https://github.com/boblail/nested_editor_for
|
62
|
+
licenses: []
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 2.2.2
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: Extends FormBuilder to support editing child records
|
84
|
+
test_files: []
|