cocoon 1.1.0 → 1.1.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 +5 -0
- data/README.markdown +97 -0
- data/VERSION +1 -1
- data/app/assets/javascripts/cocoon.js +32 -32
- data/cocoon.gemspec +2 -2
- data/lib/cocoon/view_helpers.rb +16 -12
- data/spec/cocoon_spec.rb +63 -40
- metadata +3 -3
data/History.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Change History / Release Notes
|
2
2
|
|
3
|
+
## Version 1.1.1
|
4
|
+
|
5
|
+
* added the to be added/deleted element to the event, this allows to add animations/actions onto them
|
6
|
+
* added extra option :wrap_object, allowing to use Decorators instead of the association object
|
7
|
+
* added an option :force_non_association_create, that will allow to use `link_to_add_association` inside the fields-partial
|
3
8
|
|
4
9
|
## Version 1.1.0
|
5
10
|
|
data/README.markdown
CHANGED
@@ -216,6 +216,8 @@ It takes four parameters:
|
|
216
216
|
- `partial`: explicitly declare the name of the partial that will be used
|
217
217
|
- `render_options` : options passed through to the form-builder function (e.g. `simple_fields_for`, `semantic_fields_for` or `fields_for`).
|
218
218
|
If it contains a `:locals` option containing a hash, that is handed to the partial.
|
219
|
+
- `wrap_object` : a proc that will allow to wrap your object, especially useful if you are using decorators (e.g. draper). See example lower.
|
220
|
+
- `force_non_association_create`: if true, it will _not_ create the new object using the association (see lower)
|
219
221
|
|
220
222
|
Optionally you could also leave out the name and supply a block that is captured to give the name (if you want to do something more complicated).
|
221
223
|
|
@@ -245,6 +247,65 @@ To overrule the default partial name, e.g. because it shared between multiple vi
|
|
245
247
|
= link_to_add_association 'add something', f, :something, :partial => 'shared/something_fields'
|
246
248
|
````
|
247
249
|
|
250
|
+
#### :wrap_object
|
251
|
+
|
252
|
+
If you are using decorators, the normal instantiation of the associated will not be enough, actually you want to generate the decorated object.
|
253
|
+
|
254
|
+
A simple decorator would look like:
|
255
|
+
|
256
|
+
```
|
257
|
+
class CommentDecorator
|
258
|
+
def initialize(comment)
|
259
|
+
@comment = comment
|
260
|
+
end
|
261
|
+
|
262
|
+
def formatted_created_at
|
263
|
+
@comment.created_at.to_formatted_s(:short)
|
264
|
+
end
|
265
|
+
|
266
|
+
def method_missing(method_sym, *args)
|
267
|
+
if @comment.respond_to?(method_sym)
|
268
|
+
@comment.send(method_sym, *args)
|
269
|
+
else
|
270
|
+
super
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
```
|
275
|
+
|
276
|
+
To use this, write
|
277
|
+
|
278
|
+
```
|
279
|
+
link_to_add_association('add something', @form_obj, :comments, :wrap_object => Proc.new {|comment| CommentDecorator.new(comment) })
|
280
|
+
```
|
281
|
+
|
282
|
+
Note that the `:wrap_object` expects an object that is _callable_, so any `Proc` will do. So you could as well use it to do some fancy extra initialisation (if needed).
|
283
|
+
But note you will have to return the (nested) object you want used.
|
284
|
+
E.g.
|
285
|
+
|
286
|
+
|
287
|
+
```
|
288
|
+
link_to_add_association('add something', @form_obj, :comments,
|
289
|
+
:wrap_object => Proc.new { |comment| comment.name = current_user.name; comment })
|
290
|
+
```
|
291
|
+
|
292
|
+
#### :force_non_association_create
|
293
|
+
|
294
|
+
In normal cases we create a new nested object using the association relation itself. This is the cleanest way to create
|
295
|
+
a new nested object. But this has a side-effect: for each call of `link_to_add_association` a new element is added to the association.
|
296
|
+
|
297
|
+
In most cases this is not a problem, but if you want to render a `link_to_add_association` for each nested element this will result
|
298
|
+
in an infinite loop.
|
299
|
+
|
300
|
+
To resolve this, specify that `:force_non_association_create` should be `true`, as follows:
|
301
|
+
|
302
|
+
```
|
303
|
+
link_to_add_association('add something', @form_obj, :comments, :force_non_association_create => true)
|
304
|
+
```
|
305
|
+
|
306
|
+
By default `:force_non_association_create` is `false`.
|
307
|
+
|
308
|
+
> A cleaner option would be to call a function that performs this initialisation and returns `self` at the end.
|
248
309
|
|
249
310
|
### link_to_remove_association
|
250
311
|
|
@@ -269,6 +330,16 @@ On insertion or removal the following events are triggered:
|
|
269
330
|
* `cocoon:before-remove`: called before removing the nested child
|
270
331
|
* `cocoon:after-remove`: called after removal
|
271
332
|
|
333
|
+
To listen to the events, you to have the following code in your javascript:
|
334
|
+
|
335
|
+
$('#container').bind('cocoon:before-insert', function(e, inserted_item) {
|
336
|
+
// ... do something
|
337
|
+
});
|
338
|
+
|
339
|
+
where `e` is the event and the second parameter is the inserted or removed item. This allows you to change markup, or
|
340
|
+
add effects/animations (see example below).
|
341
|
+
|
342
|
+
|
272
343
|
If in your view you have the following snippet to select an `owner`
|
273
344
|
(we use slim for demonstration purposes)
|
274
345
|
|
@@ -304,12 +375,38 @@ $(document).ready(function() {
|
|
304
375
|
function() {
|
305
376
|
/* e.g. recalculate order of child items */
|
306
377
|
});
|
378
|
+
|
379
|
+
// example showing manipulating the inserted/removed item
|
380
|
+
|
381
|
+
$('#tasks').bind('cocoon:before-insert', function(e,task_to_be_added) {
|
382
|
+
task_to_be_added.fadeIn('slow');
|
383
|
+
});
|
384
|
+
|
385
|
+
$('#tasks').bind('cocoon:after-insert', function(e, added_task) {
|
386
|
+
// e.g. set the background of inserted task
|
387
|
+
added_task.css("background","red");
|
388
|
+
});
|
389
|
+
|
390
|
+
$('#tasks').bind('cocoon:before-remove', function(e, task) {
|
391
|
+
// allow some time for the animation to complete
|
392
|
+
$(this).data('remove-timeout', 1000);
|
393
|
+
task.fadeOut('slow');
|
394
|
+
})
|
395
|
+
|
396
|
+
|
307
397
|
});
|
308
398
|
````
|
309
399
|
|
310
400
|
Do note that for the callbacks to work there has to be a surrounding container (div), where you can bind the callbacks to.
|
311
401
|
|
312
402
|
|
403
|
+
When adding animations and effects to make the removal of items more interesting, you will also have to provide a timeout.
|
404
|
+
This is accomplished by the following line:
|
405
|
+
|
406
|
+
$(this).data('remove-timeout', 1000);
|
407
|
+
|
408
|
+
Note that you could also immediately add this to your view (on the `.nested-fields` container).
|
409
|
+
|
313
410
|
### Control the Insertion behaviour
|
314
411
|
|
315
412
|
The default insertion location is at the back of the current container. But we have added two `data`-attributes that are read to determine the insertion-node and -method.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.1.
|
1
|
+
1.1.1
|
@@ -1,17 +1,12 @@
|
|
1
1
|
(function($) {
|
2
2
|
|
3
|
+
var cocoon_element_counter = 0;
|
4
|
+
|
3
5
|
function replace_in_content(content, regexp_str, with_str) {
|
4
6
|
reg_exp = new RegExp(regexp_str);
|
5
7
|
content.replace(reg_exp, with_str);
|
6
8
|
}
|
7
9
|
|
8
|
-
function trigger_before_removal_callback(node) {
|
9
|
-
node.trigger('cocoon:before-remove');
|
10
|
-
}
|
11
|
-
|
12
|
-
function trigger_after_removal_callback(node) {
|
13
|
-
node.trigger('cocoon:after-remove');
|
14
|
-
}
|
15
10
|
|
16
11
|
$('.add_fields').live('click', function(e) {
|
17
12
|
e.preventDefault();
|
@@ -22,20 +17,20 @@
|
|
22
17
|
insertionMethod = $this.data('association-insertion-method') || $this.data('association-insertion-position') || 'before';
|
23
18
|
insertionNode = $this.data('association-insertion-node'),
|
24
19
|
insertionTraversal = $this.data('association-insertion-traversal'),
|
25
|
-
regexp_braced = new RegExp('\\[new_' + assoc + '\\]', 'g'),
|
26
|
-
regexp_underscord = new RegExp('_new_' + assoc + '_', 'g'),
|
27
|
-
new_id = new Date().getTime()
|
20
|
+
regexp_braced = new RegExp('\\[new_' + assoc + '\\](.*?\\s)', 'g'),
|
21
|
+
regexp_underscord = new RegExp('_new_' + assoc + '_(\\w*)', 'g'),
|
22
|
+
new_id = new Date().getTime() + cocoon_element_counter++,
|
28
23
|
newcontent_braced = '[' + new_id + ']',
|
29
24
|
newcontent_underscord = '_' + new_id + '_',
|
30
|
-
new_content = content.replace(regexp_braced, '[' + new_id + ']');
|
25
|
+
new_content = content.replace(regexp_braced, '[' + new_id + ']$1');
|
31
26
|
|
32
27
|
if (new_content == content) {
|
33
|
-
regexp_braced = new RegExp('\\[new_' + assocs + '\\]', 'g');
|
34
|
-
regexp_underscord = new RegExp('_new_' + assocs + '_', 'g');
|
35
|
-
new_content = content.replace(regexp_braced, '[' + new_id + ']');
|
28
|
+
regexp_braced = new RegExp('\\[new_' + assocs + '\\](.*?\\s)', 'g');
|
29
|
+
regexp_underscord = new RegExp('_new_' + assocs + '_(\\w*)', 'g');
|
30
|
+
new_content = content.replace(regexp_braced, '[' + new_id + ']$1');
|
36
31
|
}
|
37
32
|
|
38
|
-
new_content = new_content.replace(regexp_underscord, newcontent_underscord);
|
33
|
+
new_content = new_content.replace(regexp_underscord, newcontent_underscord + "$1");
|
39
34
|
|
40
35
|
if (insertionNode){
|
41
36
|
if (insertionTraversal){
|
@@ -49,33 +44,38 @@
|
|
49
44
|
|
50
45
|
var contentNode = $(new_content);
|
51
46
|
|
52
|
-
insertionNode.trigger('cocoon:before-insert');
|
47
|
+
insertionNode.trigger('cocoon:before-insert', [contentNode]);
|
53
48
|
|
54
49
|
// allow any of the jquery dom manipulation methods (after, before, append, prepend, etc)
|
55
50
|
// to be called on the node. allows the insertion node to be the parent of the inserted
|
56
51
|
// code and doesn't force it to be a sibling like after/before does. default: 'before'
|
57
|
-
insertionNode[insertionMethod](contentNode);
|
52
|
+
var addedContent = insertionNode[insertionMethod](contentNode);
|
58
53
|
|
59
|
-
insertionNode.trigger('cocoon:after-insert');
|
54
|
+
insertionNode.trigger('cocoon:after-insert', [contentNode]);
|
60
55
|
});
|
61
56
|
|
62
|
-
$('.remove_fields.dynamic').live('click', function(e) {
|
63
|
-
var $this = $(this);
|
64
|
-
var trigger_node = $this.closest(".nested-fields").parent();
|
65
|
-
trigger_before_removal_callback(trigger_node);
|
66
|
-
e.preventDefault();
|
67
|
-
$this.closest(".nested-fields").remove();
|
68
|
-
trigger_after_removal_callback(trigger_node);
|
69
|
-
});
|
70
57
|
|
71
|
-
$('.remove_fields.existing').live('click', function(e) {
|
58
|
+
$('.remove_fields.dynamic, .remove_fields.existing').live('click', function(e) {
|
72
59
|
var $this = $(this);
|
73
|
-
var
|
74
|
-
|
60
|
+
var node_to_delete = $this.closest(".nested-fields");
|
61
|
+
var trigger_node = node_to_delete.parent();
|
62
|
+
|
75
63
|
e.preventDefault();
|
76
|
-
|
77
|
-
|
78
|
-
|
64
|
+
|
65
|
+
trigger_node.trigger('cocoon:before-remove', [node_to_delete]);
|
66
|
+
|
67
|
+
|
68
|
+
var timeout = trigger_node.data('remove-timeout') || 0;
|
69
|
+
|
70
|
+
setTimeout(function() {
|
71
|
+
if ($this.hasClass('dynamic')) {
|
72
|
+
$this.closest(".nested-fields").remove();
|
73
|
+
} else {
|
74
|
+
$this.prev("input[type=hidden]").val("1");
|
75
|
+
$this.closest(".nested-fields").hide();
|
76
|
+
}
|
77
|
+
trigger_node.trigger('cocoon:after-remove', [node_to_delete]);
|
78
|
+
}, timeout);
|
79
79
|
});
|
80
80
|
|
81
81
|
})(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.1.
|
8
|
+
s.version = "1.1.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 = "2012-
|
12
|
+
s.date = "2012-11-22"
|
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
@@ -50,6 +50,8 @@ module Cocoon
|
|
50
50
|
# - *:render_options* : options passed to `simple_fields_for, semantic_fields_for or fields_for`
|
51
51
|
# - *:locals* : the locals hash in the :render_options is handed to the partial
|
52
52
|
# - *:partial* : explicitly override the default partial name
|
53
|
+
# - *:wrap_object : !!! document more here !!!
|
54
|
+
# - *!!!add some option to build in collection or not!!!*
|
53
55
|
# - *&block*: see <tt>link_to</tt>
|
54
56
|
|
55
57
|
def link_to_add_association(*args, &block)
|
@@ -68,16 +70,14 @@ module Cocoon
|
|
68
70
|
render_options ||= {}
|
69
71
|
override_partial = html_options.delete(:partial)
|
70
72
|
wrap_object = html_options.delete(:wrap_object)
|
73
|
+
force_non_association_create = html_options.delete(:force_non_association_create) || false
|
71
74
|
|
72
75
|
html_options[:class] = [html_options[:class], "add_fields"].compact.join(' ')
|
73
76
|
html_options[:'data-association'] = association.to_s.singularize
|
74
77
|
html_options[:'data-associations'] = association.to_s.pluralize
|
75
78
|
|
76
|
-
|
77
|
-
|
78
|
-
else
|
79
|
-
new_object = create_object(f, association)
|
80
|
-
end
|
79
|
+
new_object = create_object(f, association, force_non_association_create)
|
80
|
+
new_object = wrap_object.call(new_object) if wrap_object.respond_to?(:call)
|
81
81
|
|
82
82
|
html_options[:'data-association-insertion-template'] = CGI.escapeHTML(render_association(association, f, new_object, render_options, override_partial)).html_safe
|
83
83
|
|
@@ -89,10 +89,10 @@ module Cocoon
|
|
89
89
|
# `` has_many :admin_comments, class_name: "Comment", conditions: { author: "Admin" }
|
90
90
|
# will create new Comment with author "Admin"
|
91
91
|
|
92
|
-
def create_object(f, association)
|
92
|
+
def create_object(f, association, force_non_association_create=false)
|
93
93
|
assoc = f.object.class.reflect_on_association(association)
|
94
94
|
|
95
|
-
assoc ? create_object_on_association(f, association, assoc) : create_object_on_non_association(f, association)
|
95
|
+
assoc ? create_object_on_association(f, association, assoc, force_non_association_create) : create_object_on_non_association(f, association)
|
96
96
|
end
|
97
97
|
|
98
98
|
def get_partial_path(partial, association)
|
@@ -107,13 +107,12 @@ module Cocoon
|
|
107
107
|
raise "Association #{association} doesn't exist on #{f.object.class}"
|
108
108
|
end
|
109
109
|
|
110
|
-
def create_object_on_association(f, association, instance)
|
111
|
-
if instance.class.name == "Mongoid::Relations::Metadata"
|
112
|
-
|
113
|
-
instance.klass.new(*conditions)
|
110
|
+
def create_object_on_association(f, association, instance, force_non_association_create)
|
111
|
+
if instance.class.name == "Mongoid::Relations::Metadata" || force_non_association_create
|
112
|
+
create_object_with_conditions(instance)
|
114
113
|
else
|
115
114
|
# assume ActiveRecord or compatible
|
116
|
-
if
|
115
|
+
if instance.collection?
|
117
116
|
f.object.send(association).build
|
118
117
|
else
|
119
118
|
f.object.send("build_#{association}")
|
@@ -121,5 +120,10 @@ module Cocoon
|
|
121
120
|
end
|
122
121
|
end
|
123
122
|
|
123
|
+
def create_object_with_conditions(instance)
|
124
|
+
conditions = instance.respond_to?(:conditions) ? instance.conditions.flatten : []
|
125
|
+
instance.klass.new(*conditions)
|
126
|
+
end
|
127
|
+
|
124
128
|
end
|
125
129
|
end
|
data/spec/cocoon_spec.rb
CHANGED
@@ -10,11 +10,15 @@ describe Cocoon do
|
|
10
10
|
it { should respond_to(:link_to_add_association) }
|
11
11
|
it { should respond_to(:link_to_remove_association) }
|
12
12
|
|
13
|
+
before(:each) do
|
14
|
+
@tester = TestClass.new
|
15
|
+
@post = Post.new
|
16
|
+
@form_obj = stub(:object => @post, :object_name => @post.class.name)
|
17
|
+
end
|
18
|
+
|
19
|
+
|
13
20
|
context "link_to_add_association" do
|
14
21
|
before(:each) do
|
15
|
-
@tester = TestClass.new
|
16
|
-
@post = Post.new
|
17
|
-
@form_obj = stub(:object => @post)
|
18
22
|
@tester.stub(:render_association).and_return('form<tag>')
|
19
23
|
end
|
20
24
|
|
@@ -41,6 +45,25 @@ describe Cocoon do
|
|
41
45
|
@tester.should_receive(:render_association).with(anything(), anything(), kind_of(CommentDecorator), anything(), anything()).and_return('partiallll')
|
42
46
|
@tester.link_to_add_association('add something', @form_obj, :comments, :wrap_object => Proc.new {|comment| CommentDecorator.new(comment) })
|
43
47
|
end
|
48
|
+
|
49
|
+
context "force non association create" do
|
50
|
+
it "default it uses the association" do
|
51
|
+
@tester.should_receive(:create_object).with(anything, :comments , false)
|
52
|
+
result = @tester.link_to_add_association('add something', @form_obj, :comments)
|
53
|
+
result.to_s.should == '<a href="#" class="add_fields" data-association-insertion-template="form<tag>" data-association="comment" data-associations="comments">add something</a>'
|
54
|
+
end
|
55
|
+
it "specifying false is the same as default: create object on association" do
|
56
|
+
@tester.should_receive(:create_object).with(anything, :comments , false)
|
57
|
+
result = @tester.link_to_add_association('add something', @form_obj, :comments, :force_non_association_create => false)
|
58
|
+
result.to_s.should == '<a href="#" class="add_fields" data-association-insertion-template="form<tag>" data-association="comment" data-associations="comments">add something</a>'
|
59
|
+
end
|
60
|
+
it "specifying true will not create objects on association but using the conditions" do
|
61
|
+
@tester.should_receive(:create_object).with(anything, :comments , true)
|
62
|
+
result = @tester.link_to_add_association('add something', @form_obj, :comments, :force_non_association_create => true)
|
63
|
+
result.to_s.should == '<a href="#" class="add_fields" data-association-insertion-template="form<tag>" data-association="comment" data-associations="comments">add something</a>'
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
44
67
|
end
|
45
68
|
|
46
69
|
context "with a block" do
|
@@ -146,12 +169,6 @@ describe Cocoon do
|
|
146
169
|
end
|
147
170
|
|
148
171
|
context "link_to_remove_association" do
|
149
|
-
before(:each) do
|
150
|
-
@tester = TestClass.new
|
151
|
-
@post = Post.new
|
152
|
-
@form_obj = stub(:object => @post, :object_name => @post.class.name)
|
153
|
-
end
|
154
|
-
|
155
172
|
context "without a block" do
|
156
173
|
it "accepts a name" do
|
157
174
|
result = @tester.link_to_remove_association('remove something', @form_obj)
|
@@ -180,44 +197,50 @@ describe Cocoon do
|
|
180
197
|
result.to_s.should == "<input id=\"Post__destroy\" name=\"Post[_destroy]\" type=\"hidden\" /><a href=\"#\" class=\"add_some_class remove_fields dynamic\" data-something=\"bla\">remove some long name</a>"
|
181
198
|
end
|
182
199
|
end
|
200
|
+
end
|
183
201
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
202
|
+
context "create_object" do
|
203
|
+
it "creates correct association with conditions" do
|
204
|
+
@tester.should_not_receive(:create_object_with_conditions)
|
205
|
+
result = @tester.create_object(@form_obj, :admin_comments)
|
206
|
+
result.author.should == "Admin"
|
207
|
+
end
|
189
208
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
209
|
+
it "creates correct association for belongs_to associations" do
|
210
|
+
result = @tester.create_object(stub(:object => Comment.new), :post)
|
211
|
+
result.should be_a Post
|
212
|
+
end
|
194
213
|
|
195
|
-
|
196
|
-
|
197
|
-
|
214
|
+
it "raises an error if cannot reflect on association" do
|
215
|
+
expect { @tester.create_object(stub(:object => Comment.new), :not_existing) }.to raise_error /association/i
|
216
|
+
end
|
198
217
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
218
|
+
it "creates an association if object responds to 'build_association' as singular" do
|
219
|
+
object = Comment.new
|
220
|
+
object.should_receive(:build_custom_item).and_return 'custom'
|
221
|
+
@tester.create_object(stub(:object => object), :custom_item).should == 'custom'
|
222
|
+
end
|
204
223
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
end
|
224
|
+
it "creates an association if object responds to 'build_association' as plural" do
|
225
|
+
object = Comment.new
|
226
|
+
object.should_receive(:build_custom_item).and_return 'custom'
|
227
|
+
@tester.create_object(stub(:object => object), :custom_items).should == 'custom'
|
210
228
|
end
|
211
229
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
230
|
+
it "can create using only conditions not the association" do
|
231
|
+
@tester.should_receive(:create_object_with_conditions).and_return('flappie')
|
232
|
+
@tester.create_object(@form_obj, :comments, true).should == 'flappie'
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context "get_partial_path" do
|
237
|
+
it "generates the default partial name if no partial given" do
|
238
|
+
result = @tester.get_partial_path(nil, :admin_comments)
|
239
|
+
result.should == "admin_comment_fields"
|
240
|
+
end
|
241
|
+
it "uses the given partial name" do
|
242
|
+
result = @tester.get_partial_path("comment_fields", :admin_comments)
|
243
|
+
result.should == "comment_fields"
|
221
244
|
end
|
222
245
|
end
|
223
246
|
|
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.1.
|
4
|
+
version: 1.1.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: 2012-
|
12
|
+
date: 2012-11-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -248,7 +248,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
248
248
|
version: '0'
|
249
249
|
segments:
|
250
250
|
- 0
|
251
|
-
hash: -
|
251
|
+
hash: -2830798901960136537
|
252
252
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
253
253
|
none: false
|
254
254
|
requirements:
|