cocoon 1.2.0 → 1.2.1
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/History.md +15 -0
- data/README.markdown +37 -16
- data/VERSION +1 -1
- data/app/assets/javascripts/cocoon.js +4 -5
- data/cocoon.gemspec +2 -2
- data/lib/cocoon/view_helpers.rb +22 -9
- data/spec/cocoon_spec.rb +42 -5
- data/spec/dummy/config/environments/development.rb +1 -2
- data/spec/dummy/config/environments/production.rb +1 -0
- data/spec/dummy/config/environments/test.rb +1 -3
- metadata +3 -3
data/History.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Change History / Release Notes
|
2
2
|
|
3
|
+
## Version 1.2.1
|
4
|
+
|
5
|
+
* added a `:form_name` parameter (fixes #153) which allows to use a self-chosen
|
6
|
+
parameter in the nested views. Up until now `f` was assumed (and enforced).
|
7
|
+
* improvement of creation of the objects on the association (thanks to Dirk von Grünigen). This
|
8
|
+
alleviates the need for the `:force_non_association_create` option in most cases.
|
9
|
+
That option is for now still kept.
|
10
|
+
* after validation errors, already deleted (but not saved) nested elements, will remain deleted
|
11
|
+
(e.g. the state is remembered, and they remain hidden, and will be correctly deleted on next
|
12
|
+
succesfull save) (fixes #136).
|
13
|
+
|
14
|
+
## Version 1.2.0
|
15
|
+
|
16
|
+
* support for rails 4.0
|
17
|
+
|
3
18
|
## Version 1.1.2
|
4
19
|
|
5
20
|
* pull #118 (thanks @ahmozkya): remove the deprecated `.live` function, and use `.on` instead.
|
data/README.markdown
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# cocoon
|
2
2
|
|
3
|
-
[](https://travis-ci.org/nathanvda/cocoon)
|
3
|
+
[](https://travis-ci.org/nathanvda/cocoon)
|
4
4
|
|
5
5
|
Cocoon makes it easier to handle nested forms.
|
6
6
|
|
@@ -25,8 +25,9 @@ Inside your `Gemfile` add the following:
|
|
25
25
|
gem "cocoon"
|
26
26
|
```
|
27
27
|
|
28
|
+
> Please note that for rails 4 you will need at least v1.2.0 or later.
|
28
29
|
|
29
|
-
### Rails 3.1
|
30
|
+
### Rails 3.1+/Rails 4
|
30
31
|
|
31
32
|
Add the following to `application.js` so it compiles to the asset pipeline:
|
32
33
|
|
@@ -79,6 +80,24 @@ Now we want a project form where we can add and remove tasks dynamically.
|
|
79
80
|
To do this, we need the fields for a new or existing `task` to be defined in a partial
|
80
81
|
named `_task_fields.html`.
|
81
82
|
|
83
|
+
### Strong Parameters Gotcha
|
84
|
+
|
85
|
+
To destroy nested models, rails uses a virtual attribute called `_destroy`.
|
86
|
+
When `_destroy` is set, the nested model will be deleted.
|
87
|
+
|
88
|
+
When using strong parameters (default in rails 4), you need to explicitly
|
89
|
+
add `:_destroy` to the list of permitted parameters.
|
90
|
+
|
91
|
+
E.g. in your `ProjectsController`:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
def project_params
|
95
|
+
params.require(:project).permit(:name, :description, tasks_attributes: [:id, :description, :done, :_destroy])
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
|
100
|
+
|
82
101
|
## Examples
|
83
102
|
|
84
103
|
### Formtastic
|
@@ -202,6 +221,7 @@ This should be called within the form builder.
|
|
202
221
|
If it contains a `:locals` option containing a hash, that is handed to the partial.
|
203
222
|
- `wrap_object` : a proc that will allow to wrap your object, especially useful if you are using decorators (e.g. draper). See example lower.
|
204
223
|
- `force_non_association_create`: if true, it will _not_ create the new object using the association (see lower)
|
224
|
+
- `form_name` : the name of the form parameter in your nested partial. By default this is `f`.
|
205
225
|
|
206
226
|
Optionally, you can omit the name and supply a block that is captured to render the link body (if you want to do something more complicated).
|
207
227
|
|
@@ -281,12 +301,15 @@ E.g.
|
|
281
301
|
#### :force_non_association_create
|
282
302
|
|
283
303
|
In normal cases we create a new nested object using the association relation itself. This is the cleanest way to create
|
284
|
-
a new nested object.
|
304
|
+
a new nested object.
|
305
|
+
|
306
|
+
This used to have a side-effect: for each call of `link_to_add_association` a new element was added to the association.
|
307
|
+
This is no longer the case.
|
285
308
|
|
286
|
-
|
287
|
-
|
309
|
+
For backward compatibility we keep this option for now. Or if for some specific reason you would
|
310
|
+
really need an object to be _not_ created on the association.
|
288
311
|
|
289
|
-
|
312
|
+
Example use:
|
290
313
|
|
291
314
|
```haml
|
292
315
|
= link_to_add_association('add something', @form_obj, :comments,
|
@@ -295,8 +318,6 @@ To resolve this, specify that `:force_non_association_create` should be `true`:
|
|
295
318
|
|
296
319
|
By default `:force_non_association_create` is `false`.
|
297
320
|
|
298
|
-
> A cleaner option would be to call a function that performs this initialisation and returns `self` at the end.
|
299
|
-
|
300
321
|
### link_to_remove_association
|
301
322
|
|
302
323
|
This function will add a link to your markup that, when clicked, dynamically removes the surrounding partial form.
|
@@ -323,7 +344,7 @@ On insertion or removal the following events are triggered:
|
|
323
344
|
To listen to the events in your JavaScript:
|
324
345
|
|
325
346
|
```javascript
|
326
|
-
$('#container').
|
347
|
+
$('#container').on('cocoon:before-insert', function(e, insertedItem) {
|
327
348
|
// ... do something
|
328
349
|
});
|
329
350
|
```
|
@@ -348,32 +369,32 @@ The callbacks can be added as follows:
|
|
348
369
|
```javascript
|
349
370
|
$(document).ready(function() {
|
350
371
|
$('#owner')
|
351
|
-
.
|
372
|
+
.on('cocoon:before-insert', function() {
|
352
373
|
$("#owner_from_list").hide();
|
353
374
|
$("#owner a.add_fields").hide();
|
354
375
|
})
|
355
|
-
.
|
376
|
+
.on('cocoon:after-insert', function() {
|
356
377
|
/* ... do something ... */
|
357
378
|
})
|
358
|
-
.
|
379
|
+
.on("cocoon:before-remove", function() {
|
359
380
|
$("#owner_from_list").show();
|
360
381
|
$("#owner a.add_fields").show();
|
361
382
|
})
|
362
|
-
.
|
383
|
+
.on("cocoon:after-remove", function() {
|
363
384
|
/* e.g. recalculate order of child items */
|
364
385
|
});
|
365
386
|
|
366
387
|
// example showing manipulating the inserted/removed item
|
367
388
|
|
368
389
|
$('#tasks')
|
369
|
-
.
|
390
|
+
.on('cocoon:before-insert', function(e,task_to_be_added) {
|
370
391
|
task_to_be_added.fadeIn('slow');
|
371
392
|
})
|
372
|
-
.
|
393
|
+
.on('cocoon:after-insert', function(e, added_task) {
|
373
394
|
// e.g. set the background of inserted task
|
374
395
|
added_task.css("background","red");
|
375
396
|
})
|
376
|
-
.
|
397
|
+
.on('cocoon:before-remove', function(e, task) {
|
377
398
|
// allow some time for the animation to complete
|
378
399
|
$(this).data('remove-timeout', 1000);
|
379
400
|
task.fadeOut('slow');
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.2.
|
1
|
+
1.2.1
|
@@ -7,14 +7,13 @@
|
|
7
7
|
content.replace(reg_exp, with_str);
|
8
8
|
}
|
9
9
|
|
10
|
-
|
11
10
|
$(document).on('click', '.add_fields', function(e) {
|
12
11
|
e.preventDefault();
|
13
12
|
var $this = $(this),
|
14
13
|
assoc = $this.data('association'),
|
15
14
|
assocs = $this.data('associations'),
|
16
15
|
content = $this.data('association-insertion-template'),
|
17
|
-
insertionMethod = $this.data('association-insertion-method') || $this.data('association-insertion-position') || 'before'
|
16
|
+
insertionMethod = $this.data('association-insertion-method') || $this.data('association-insertion-position') || 'before',
|
18
17
|
insertionNode = $this.data('association-insertion-node'),
|
19
18
|
insertionTraversal = $this.data('association-insertion-traversal'),
|
20
19
|
regexp_braced = new RegExp('\\[new_' + assoc + '\\](.*?\\s)', 'g'),
|
@@ -34,7 +33,7 @@
|
|
34
33
|
|
35
34
|
if (insertionNode){
|
36
35
|
if (insertionTraversal){
|
37
|
-
insertionNode = $this[insertionTraversal](insertionNode)
|
36
|
+
insertionNode = $this[insertionTraversal](insertionNode);
|
38
37
|
} else {
|
39
38
|
insertionNode = insertionNode == "this" ? $this : $(insertionNode);
|
40
39
|
}
|
@@ -54,7 +53,6 @@
|
|
54
53
|
insertionNode.trigger('cocoon:after-insert', [contentNode]);
|
55
54
|
});
|
56
55
|
|
57
|
-
|
58
56
|
$(document).on('click', '.remove_fields.dynamic, .remove_fields.existing', function(e) {
|
59
57
|
var $this = $(this);
|
60
58
|
var node_to_delete = $this.closest(".nested-fields");
|
@@ -64,7 +62,6 @@
|
|
64
62
|
|
65
63
|
trigger_node.trigger('cocoon:before-remove', [node_to_delete]);
|
66
64
|
|
67
|
-
|
68
65
|
var timeout = trigger_node.data('remove-timeout') || 0;
|
69
66
|
|
70
67
|
setTimeout(function() {
|
@@ -78,4 +75,6 @@
|
|
78
75
|
}, timeout);
|
79
76
|
});
|
80
77
|
|
78
|
+
$('.remove_fields.existing.destroyed').closest('.nested-fields').hide();
|
79
|
+
|
81
80
|
})(jQuery);
|
data/cocoon.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "cocoon"
|
8
|
-
s.version = "1.2.
|
8
|
+
s.version = "1.2.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Nathan Van der Auwera"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-09-25"
|
13
13
|
s.description = "Unobtrusive nested forms handling, using jQuery. Use this and discover cocoon-heaven."
|
14
14
|
s.email = "nathan@dixis.com"
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/cocoon/view_helpers.rb
CHANGED
@@ -25,18 +25,23 @@ module Cocoon
|
|
25
25
|
html_options = args[2] || {}
|
26
26
|
|
27
27
|
is_dynamic = f.object.new_record?
|
28
|
-
|
29
|
-
|
28
|
+
|
29
|
+
classes = []
|
30
|
+
classes << "remove_fields"
|
31
|
+
classes << (is_dynamic ? 'dynamic' : 'existing')
|
32
|
+
classes << 'destroyed' if f.object.marked_for_destruction?
|
33
|
+
html_options[:class] = [html_options[:class], classes.join(' ')].compact.join(' ')
|
34
|
+
hidden_field_tag("#{f.object_name}[_destroy]", f.object._destroy) + link_to(name, '#', html_options)
|
30
35
|
end
|
31
36
|
end
|
32
37
|
|
33
38
|
# :nodoc:
|
34
|
-
def render_association(association, f, new_object, render_options={}, custom_partial=nil)
|
39
|
+
def render_association(association, f, new_object, form_name, render_options={}, custom_partial=nil)
|
35
40
|
partial = get_partial_path(custom_partial, association)
|
36
41
|
locals = render_options.delete(:locals) || {}
|
37
42
|
method_name = f.respond_to?(:semantic_fields_for) ? :semantic_fields_for : (f.respond_to?(:simple_fields_for) ? :simple_fields_for : :fields_for)
|
38
43
|
f.send(method_name, association, new_object, {:child_index => "new_#{association}"}.merge(render_options)) do |builder|
|
39
|
-
partial_options = {
|
44
|
+
partial_options = {form_name.to_sym => builder, :dynamic => true}.merge(locals)
|
40
45
|
render(partial, partial_options)
|
41
46
|
end
|
42
47
|
end
|
@@ -50,8 +55,9 @@ module Cocoon
|
|
50
55
|
# - *:render_options* : options passed to `simple_fields_for, semantic_fields_for or fields_for`
|
51
56
|
# - *:locals* : the locals hash in the :render_options is handed to the partial
|
52
57
|
# - *:partial* : explicitly override the default partial name
|
53
|
-
# - *:wrap_object
|
54
|
-
#
|
58
|
+
# - *:wrap_object* : a proc that will allow to wrap your object, especially suited when using
|
59
|
+
# decorators, or if you want special initialisation
|
60
|
+
# - *:form_name* : the parameter for the form in the nested form partial. Default `f`.
|
55
61
|
# - *&block*: see <tt>link_to</tt>
|
56
62
|
|
57
63
|
def link_to_add_association(*args, &block)
|
@@ -71,6 +77,7 @@ module Cocoon
|
|
71
77
|
override_partial = html_options.delete(:partial)
|
72
78
|
wrap_object = html_options.delete(:wrap_object)
|
73
79
|
force_non_association_create = html_options.delete(:force_non_association_create) || false
|
80
|
+
form_parameter_name = html_options.delete(:form_name) || 'f'
|
74
81
|
|
75
82
|
html_options[:class] = [html_options[:class], "add_fields"].compact.join(' ')
|
76
83
|
html_options[:'data-association'] = association.to_s.singularize
|
@@ -79,7 +86,7 @@ module Cocoon
|
|
79
86
|
new_object = create_object(f, association, force_non_association_create)
|
80
87
|
new_object = wrap_object.call(new_object) if wrap_object.respond_to?(:call)
|
81
88
|
|
82
|
-
html_options[:'data-association-insertion-template'] = CGI.escapeHTML(render_association(association, f, new_object, render_options, override_partial)).html_safe
|
89
|
+
html_options[:'data-association-insertion-template'] = CGI.escapeHTML(render_association(association, f, new_object, form_parameter_name, render_options, override_partial)).html_safe
|
83
90
|
|
84
91
|
link_to(name, '#', html_options )
|
85
92
|
end
|
@@ -111,12 +118,18 @@ module Cocoon
|
|
111
118
|
if instance.class.name == "Mongoid::Relations::Metadata" || force_non_association_create
|
112
119
|
create_object_with_conditions(instance)
|
113
120
|
else
|
121
|
+
assoc_obj = nil
|
122
|
+
|
114
123
|
# assume ActiveRecord or compatible
|
115
124
|
if instance.collection?
|
116
|
-
f.object.send(association).build
|
125
|
+
assoc_obj = f.object.send(association).build
|
126
|
+
f.object.send(association).delete(assoc_obj)
|
117
127
|
else
|
118
|
-
f.object.send("build_#{association}")
|
128
|
+
assoc_obj = f.object.send("build_#{association}")
|
129
|
+
f.object.send(association).delete
|
119
130
|
end
|
131
|
+
|
132
|
+
assoc_obj
|
120
133
|
end
|
121
134
|
end
|
122
135
|
|
data/spec/cocoon_spec.rb
CHANGED
@@ -44,7 +44,7 @@ describe Cocoon do
|
|
44
44
|
context "and explicitly specifying the wanted partial" do
|
45
45
|
before do
|
46
46
|
@tester.unstub(:render_association)
|
47
|
-
@tester.should_receive(:render_association).with(anything(), anything(), anything(), anything(), "shared/partial").and_return('partiallll')
|
47
|
+
@tester.should_receive(:render_association).with(anything(), anything(), anything(), "f", anything(), "shared/partial").and_return('partiallll')
|
48
48
|
@html = @tester.link_to_add_association('add something', @form_obj, :comments, :partial => "shared/partial")
|
49
49
|
end
|
50
50
|
|
@@ -53,7 +53,7 @@ describe Cocoon do
|
|
53
53
|
|
54
54
|
it "gives an opportunity to wrap/decorate created objects" do
|
55
55
|
@tester.unstub(:render_association)
|
56
|
-
@tester.should_receive(:render_association).with(anything(), anything(), kind_of(CommentDecorator), anything(), anything()).and_return('partiallll')
|
56
|
+
@tester.should_receive(:render_association).with(anything(), anything(), kind_of(CommentDecorator), "f", anything(), anything()).and_return('partiallll')
|
57
57
|
@tester.link_to_add_association('add something', @form_obj, :comments, :wrap_object => Proc.new {|comment| CommentDecorator.new(comment) })
|
58
58
|
end
|
59
59
|
|
@@ -128,7 +128,7 @@ describe Cocoon do
|
|
128
128
|
context "and explicitly specifying the wanted partial" do
|
129
129
|
before do
|
130
130
|
@tester.unstub(:render_association)
|
131
|
-
@tester.should_receive(:render_association).with(anything(), anything(), anything(), anything(), "shared/partial").and_return('partiallll')
|
131
|
+
@tester.should_receive(:render_association).with(anything(), anything(), anything(), "f", anything(), "shared/partial").and_return('partiallll')
|
132
132
|
@html = @tester.link_to_add_association( @form_obj, :comments, :class => 'floppy disk', :partial => "shared/partial") do
|
133
133
|
"some long name"
|
134
134
|
end
|
@@ -163,7 +163,7 @@ describe Cocoon do
|
|
163
163
|
context "with extra render-options for rendering the child relation" do
|
164
164
|
context "uses the correct plural" do
|
165
165
|
before do
|
166
|
-
@tester.should_receive(:render_association).with(:people, @form_obj, anything, {:wrapper => 'inline'}, nil)
|
166
|
+
@tester.should_receive(:render_association).with(:people, @form_obj, anything, "f", {:wrapper => 'inline'}, nil)
|
167
167
|
@html = @tester.link_to_add_association('add something', @form_obj, :people, :render_options => {:wrapper => 'inline'})
|
168
168
|
end
|
169
169
|
it_behaves_like "a correctly rendered add link", {association: 'person', associations: 'people' }
|
@@ -193,6 +193,17 @@ describe Cocoon do
|
|
193
193
|
end
|
194
194
|
end
|
195
195
|
|
196
|
+
context "overruling the form parameter name" do
|
197
|
+
context "when given a form_name it passes it correctly to the partials" do
|
198
|
+
before do
|
199
|
+
@tester.unstub(:render_association)
|
200
|
+
@form_obj.should_receive(:fields_for) { | association, new_object, options_hash, &block| block.call }
|
201
|
+
@tester.should_receive(:render).with("person_fields", {:people_form => nil, :dynamic=>true}).and_return ("partiallll")
|
202
|
+
@html = @tester.link_to_add_association('add something', @form_obj, :people, :form_name => 'people_form')
|
203
|
+
end
|
204
|
+
it_behaves_like "a correctly rendered add link", {template: 'partiallll', association: 'person', associations: 'people' }
|
205
|
+
end
|
206
|
+
end
|
196
207
|
|
197
208
|
|
198
209
|
context "when using formtastic" do
|
@@ -241,6 +252,7 @@ describe Cocoon do
|
|
241
252
|
removed = doc.at('input')
|
242
253
|
removed.attribute('id').value.should == "Post__destroy"
|
243
254
|
removed.attribute('name').value.should == "Post[_destroy]"
|
255
|
+
removed.attribute('value').value.should == "false"
|
244
256
|
end
|
245
257
|
|
246
258
|
it_behaves_like "a correctly rendered remove link", {}
|
@@ -255,6 +267,27 @@ describe Cocoon do
|
|
255
267
|
|
256
268
|
end
|
257
269
|
|
270
|
+
# this is needed when due to some validation error, objects that
|
271
|
+
# were already marked for destruction need to remain hidden
|
272
|
+
context "for a object marked for destruction" do
|
273
|
+
before do
|
274
|
+
@post_marked_for_destruction = Post.new
|
275
|
+
@post_marked_for_destruction.mark_for_destruction
|
276
|
+
@form_obj_destroyed = double(:object => @post_marked_for_destruction, :object_name => @post_marked_for_destruction.class.name)
|
277
|
+
@html = @tester.link_to_remove_association('remove something', @form_obj_destroyed)
|
278
|
+
end
|
279
|
+
|
280
|
+
it "is rendered inside a input element" do
|
281
|
+
doc = Nokogiri::HTML(@html)
|
282
|
+
removed = doc.at('input')
|
283
|
+
removed.attribute('id').value.should == "Post__destroy"
|
284
|
+
removed.attribute('name').value.should == "Post[_destroy]"
|
285
|
+
removed.attribute('value').value.should == "true"
|
286
|
+
end
|
287
|
+
|
288
|
+
it_behaves_like "a correctly rendered remove link", {class: 'remove_fields dynamic destroyed'}
|
289
|
+
end
|
290
|
+
|
258
291
|
context "with a block" do
|
259
292
|
context "the block gives the name" do
|
260
293
|
before do
|
@@ -287,11 +320,15 @@ describe Cocoon do
|
|
287
320
|
end
|
288
321
|
result = @tester.create_object(@form_obj, :admin_comments)
|
289
322
|
result.author.should == "Admin"
|
323
|
+
@form_obj.object.admin_comments.should be_empty
|
290
324
|
end
|
291
325
|
|
292
326
|
it "creates correct association for belongs_to associations" do
|
293
|
-
|
327
|
+
comment = Comment.new
|
328
|
+
form_obj = double(:object => Comment.new)
|
329
|
+
result = @tester.create_object(form_obj, :post)
|
294
330
|
result.should be_a Post
|
331
|
+
comment.post.should be_nil
|
295
332
|
end
|
296
333
|
|
297
334
|
it "raises an error if cannot reflect on association" do
|
@@ -6,8 +6,7 @@ Dummy::Application.configure do
|
|
6
6
|
# since you don't have to restart the webserver when you make code changes.
|
7
7
|
config.cache_classes = false
|
8
8
|
|
9
|
-
|
10
|
-
config.whiny_nils = true
|
9
|
+
config.eager_load = false
|
11
10
|
|
12
11
|
# Show full error reports and disable caching
|
13
12
|
config.consider_all_requests_local = true
|
@@ -4,6 +4,7 @@ Dummy::Application.configure do
|
|
4
4
|
# The production environment is meant for finished, "live" apps.
|
5
5
|
# Code is not reloaded between requests
|
6
6
|
config.cache_classes = true
|
7
|
+
config.eager_load = true
|
7
8
|
|
8
9
|
# Full error reports are disabled and caching is turned on
|
9
10
|
config.consider_all_requests_local = false
|
@@ -6,9 +6,7 @@ Dummy::Application.configure do
|
|
6
6
|
# your test database is "scratch space" for the test suite and is wiped
|
7
7
|
# and recreated between test runs. Don't rely on the data there!
|
8
8
|
config.cache_classes = true
|
9
|
-
|
10
|
-
# Log error messages when you accidentally call methods on nil.
|
11
|
-
config.whiny_nils = true
|
9
|
+
config.eager_load = false
|
12
10
|
|
13
11
|
# Show full error reports and disable caching
|
14
12
|
config.consider_all_requests_local = true
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cocoon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-09-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -270,7 +270,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
270
270
|
version: '0'
|
271
271
|
segments:
|
272
272
|
- 0
|
273
|
-
hash:
|
273
|
+
hash: -3336163965730752832
|
274
274
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
275
275
|
none: false
|
276
276
|
requirements:
|