assoc_whisperer 1.2.1 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/assoc_whisp.js +48 -46
- data/app/helpers/action_view/helpers/assoc_whisperer_helper.rb +16 -41
- data/app/helpers/action_view/helpers/tags/assoc_whisperer_field.rb +13 -32
- data/app/views/assoc_whisperer/list.html.erb +2 -2
- data/lib/assoc_whisperer/template.rb +39 -22
- data/lib/assoc_whisperer/version.rb +1 -1
- data/lib/assoc_whisperer.rb +4 -17
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c12d3a84dff2b3fcedf60c2abd790d235626c566
|
4
|
+
data.tar.gz: aacfc5036d39c470b1301cc6b7f853f0dded41d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 760054c15cc9fc0aea5357f11db45cfb81e5245a3747f574ba6fccc1abeb3a50aac045d17a08e26a09122f238e5744ea18239fb4775977ef388cc82bc481c9ce
|
7
|
+
data.tar.gz: 6309409f36c8087a4460dc542eaaf2b3d05fa1850f0df4cd5f2d20a4dd145eb97812a5cd4eafb542d946b9f9658576e0233bfb9c0f4917f75e33d0c45939c3bc
|
@@ -15,7 +15,7 @@ document.AssocWhisperer = (function () {
|
|
15
15
|
|
16
16
|
// This is where Whisperer Object is created - with all hidden inner methods.
|
17
17
|
function createWhisperer(dom_node) {
|
18
|
-
var el, w,
|
18
|
+
var el, w, opts, _nodes, _timer;
|
19
19
|
|
20
20
|
el = $(dom_node);
|
21
21
|
_nodes = {
|
@@ -25,22 +25,25 @@ document.AssocWhisperer = (function () {
|
|
25
25
|
list: null
|
26
26
|
};
|
27
27
|
opts = el.data('opts');
|
28
|
-
if (!opts['action']) throw 'Missing action in '+JSON.stringify(opts);
|
29
|
-
if (!opts['url']) throw 'Missing url in '+JSON.stringify(opts);
|
28
|
+
if (!opts['action']) throw 'Missing action path in '+JSON.stringify(opts);
|
30
29
|
if (typeof opts['params']!=='object') opts['params'] = {};
|
30
|
+
// opts['cs'] = parseInt(opts['cs']);
|
31
31
|
|
32
32
|
w = Object.create(proto, {
|
33
33
|
nodes: {value: _nodes},
|
34
|
-
action: {value: opts['action']},
|
35
|
-
url: {value: opts['url']},
|
36
|
-
params: {value: opts['params']},
|
37
34
|
focused: {value: false, writable: true},
|
38
35
|
filled: {value: _nodes['value_field'].val()!=='', writable: true},
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
// setting
|
37
|
+
action: {value: opts['action']},
|
38
|
+
params: {value: opts['params']}
|
42
39
|
});
|
43
|
-
|
40
|
+
// if (!isNaN(opts['cs'])) {
|
41
|
+
// // client side
|
42
|
+
// Object.defineProperties({
|
43
|
+
// client_side: {value: opts['cs']},
|
44
|
+
// full_data: {value: null, writable: true}
|
45
|
+
// });
|
46
|
+
// }
|
44
47
|
|
45
48
|
_nodes.text_field.on('keyup', function(e){
|
46
49
|
var input_text;
|
@@ -67,11 +70,11 @@ document.AssocWhisperer = (function () {
|
|
67
70
|
}
|
68
71
|
_timer = setTimeout(function () {
|
69
72
|
if (w.client_side) {
|
70
|
-
if (!w.full_data) query(w, null, function (html_text) {
|
71
|
-
w.full_data = $(html_text);
|
72
|
-
showList(digest(input_text));
|
73
|
-
});
|
74
|
-
else showList(digest(input_text));
|
73
|
+
// if (!w.full_data) query(w, null, function (html_text) {
|
74
|
+
// w.full_data = $(html_text);
|
75
|
+
// showList(digest(input_text));
|
76
|
+
// });
|
77
|
+
// else showList(digest(input_text));
|
75
78
|
}
|
76
79
|
else query(w, input_text, function (html_text) {
|
77
80
|
showList($(html_text));
|
@@ -86,20 +89,20 @@ document.AssocWhisperer = (function () {
|
|
86
89
|
var f;
|
87
90
|
if (_timer) clearTimeout(_timer);
|
88
91
|
if (w.client_side) {
|
89
|
-
f = function () {
|
90
|
-
var input_text;
|
91
|
-
if (w.filled) showList(w.full_data);
|
92
|
-
else {
|
93
|
-
input_text = _nodes['text_field'].val();
|
94
|
-
showList(digest(input_text==='' ? null : input_text));
|
95
|
-
}
|
96
|
-
_nodes['list'].focus();
|
97
|
-
};
|
98
|
-
if (!w.full_data) query(w, null, function (html_text) {
|
99
|
-
w.full_data = $(html_text);
|
100
|
-
f();
|
101
|
-
});
|
102
|
-
else f();
|
92
|
+
// f = function () {
|
93
|
+
// var input_text;
|
94
|
+
// if (w.filled) showList(w.full_data);
|
95
|
+
// else {
|
96
|
+
// input_text = _nodes['text_field'].val();
|
97
|
+
// showList(digest(input_text==='' ? null : input_text));
|
98
|
+
// }
|
99
|
+
// _nodes['list'].focus();
|
100
|
+
// };
|
101
|
+
// if (!w.full_data) query(w, null, function (html_text) {
|
102
|
+
// w.full_data = $(html_text);
|
103
|
+
// f();
|
104
|
+
// });
|
105
|
+
// else f();
|
103
106
|
}
|
104
107
|
else {
|
105
108
|
query(w, (w.filled ? null : _nodes['text_field'].val()), function (html_text) {
|
@@ -110,19 +113,19 @@ document.AssocWhisperer = (function () {
|
|
110
113
|
});
|
111
114
|
el.children('.dropdown_button').removeClass('querying'); // css class is set, hence gif gets pre-loaded
|
112
115
|
|
113
|
-
// For local full_data finds matching rows and shows them.
|
114
|
-
function digest(input_text) {
|
115
|
-
var narrowed_list = w.full_data;
|
116
|
-
if (input_text && input_text!=='') {
|
117
|
-
input_text = input_text.toLowerCase();
|
118
|
-
narrowed_list = $(narrowed_list[0].cloneNode());
|
119
|
-
w.full_data.children().each(function () {
|
120
|
-
if (this.innerText.toLowerCase().indexOf(input_text)!==-1)
|
121
|
-
narrowed_list.append($(this).clone());
|
122
|
-
});
|
123
|
-
}
|
124
|
-
return narrowed_list;
|
125
|
-
}
|
116
|
+
// // For local full_data finds matching rows and shows them.
|
117
|
+
// function digest(input_text) {
|
118
|
+
// var narrowed_list = w.full_data;
|
119
|
+
// if (input_text && input_text!=='') {
|
120
|
+
// input_text = input_text.toLowerCase();
|
121
|
+
// narrowed_list = $(narrowed_list[0].cloneNode());
|
122
|
+
// w.full_data.children().each(function () {
|
123
|
+
// if (this.innerText.toLowerCase().indexOf(input_text)!==-1)
|
124
|
+
// narrowed_list.append($(this).clone());
|
125
|
+
// });
|
126
|
+
// }
|
127
|
+
// return narrowed_list;
|
128
|
+
// }
|
126
129
|
|
127
130
|
// Attaches a List sent by html string within Whisperer's tag. Positions it underneath the text field.
|
128
131
|
function showList (list) {
|
@@ -187,8 +190,8 @@ document.AssocWhisperer = (function () {
|
|
187
190
|
klass.querying = true;
|
188
191
|
btn = w.nodes['base'].find('.dropdown_button');
|
189
192
|
btn.addClass('querying');
|
190
|
-
w.params['input'] = input
|
191
|
-
$.ajax(w.
|
193
|
+
w.params['input'] = input;
|
194
|
+
$.ajax(w.action, {
|
192
195
|
type: 'GET',
|
193
196
|
dataType: 'html',
|
194
197
|
data: w.params,
|
@@ -206,7 +209,6 @@ document.AssocWhisperer = (function () {
|
|
206
209
|
// public interface //
|
207
210
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
208
211
|
|
209
|
-
|
210
212
|
klass = Object.create(Object, {querying: {value: false, writable: true}});
|
211
213
|
|
212
214
|
// Return a Whisperer instance by its data-action attribute.
|
@@ -214,7 +216,7 @@ document.AssocWhisperer = (function () {
|
|
214
216
|
var i, w;
|
215
217
|
for (i = 0; i < all_array.length; i += 1) {
|
216
218
|
w = all_array[i];
|
217
|
-
if (w.action===action) return w;
|
219
|
+
if (w.params['action']===action || w.action.indexOf(action)!==-1) return w;
|
218
220
|
}
|
219
221
|
return null;
|
220
222
|
}
|
@@ -3,54 +3,29 @@ module ActionView
|
|
3
3
|
|
4
4
|
module AssocWhispererHelper
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# ==== Examples
|
10
|
-
# assoc_whisperer :task, :worker, :workers, size: 25, url: '/whisp'
|
11
|
-
# # => <span class="assoc_whisperer" data-action="workers" data-url="/whisp">
|
12
|
-
# <input class="value_field" id="task_worker_id" name="task[worker_id]" type="hidden" value="">
|
13
|
-
# <input autocomplete="off" class="text_field unfilled" id="task_worker_txt" name="task[worker_txt]" size="25" type="text" value="">
|
14
|
-
# <span class="dropdown_button">▾</span></span>
|
15
|
-
#
|
16
|
-
# Let's say your association looks like this:
|
17
|
-
#
|
18
|
-
# class Task
|
19
|
-
# belongs_to :worker, class_name: 'Worker', foreign_key: :manager
|
20
|
-
# end
|
21
|
-
# class Worker
|
22
|
-
# def full_name; end
|
23
|
-
# def manager_id; end
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# assoc_whisperer :task, :worker, :workers, name: :manager, value_method: :manager_id, text_method: :full_name
|
27
|
-
# # => <span class="assoc_whisperer" data-action="workers" data-url="">
|
28
|
-
# <input class="value_field" id="task_manager" name="task[manager]" type="hidden" value="">
|
29
|
-
# <input autocomplete="off" class="text_field unfilled" id="task_manager_txt" name="task[manager_txt]" size="12" type="text" value="">
|
30
|
-
# <span class="dropdown_button">▾</span></span>
|
31
|
-
#
|
32
|
-
# And the 'value_field' would be filled by +manager_id+ of +worker+ associated to +task+, 'text_field' by his +full_name+
|
33
|
-
#
|
34
|
-
def assoc_whisperer(object_name, method, data_action, options={})
|
35
|
-
raise "Helper '#assoc_whisperer' is for Rails >= 4.x. Use '#assoc_whisperer_tag' instead." if Rails::VERSION::STRING.to_i < 4
|
36
|
-
wrapper_assoc_whisperer_assets
|
6
|
+
def whisperer(object_name, method, template, field_attrs={})
|
7
|
+
raise "Helper '#whisperer' cannot be used in Rails < 4.x. Use '#whisperer_tag' instead." if Rails::VERSION::STRING.to_i < 4
|
8
|
+
wrapper_whisperer_assets
|
37
9
|
|
38
|
-
Tags::AssocWhispererField.new(object_name, method, self,
|
10
|
+
Tags::AssocWhispererField.new(object_name, method, self, template, field_attrs).render
|
39
11
|
end
|
40
12
|
|
41
|
-
def
|
42
|
-
|
13
|
+
def whisperer_tag(name, template, field_attrs={})
|
14
|
+
wrapper_whisperer_assets
|
43
15
|
|
44
|
-
|
45
|
-
|
46
|
-
|
16
|
+
content_tag :span, template.tag_contents(name, field_attrs).html_safe, 'class' => 'assoc_whisperer',
|
17
|
+
'data-opts' => template.whisperer_settings.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
def whisperer_template(action, opts={})
|
21
|
+
AssocWhisperer::Template.new action, opts
|
47
22
|
end
|
48
23
|
|
49
24
|
private
|
50
25
|
|
51
|
-
def
|
26
|
+
def wrapper_whisperer_assets
|
52
27
|
unless @assoc_whisp_attached
|
53
|
-
attach_method = AssocWhisperer.
|
28
|
+
attach_method = AssocWhisperer.attach_assets
|
54
29
|
self.send attach_method if attach_method && self.respond_to?(attach_method)
|
55
30
|
@assoc_whisp_attached = true
|
56
31
|
end
|
@@ -59,8 +34,8 @@ module ActionView
|
|
59
34
|
end
|
60
35
|
|
61
36
|
class FormBuilder
|
62
|
-
def
|
63
|
-
@template.assoc_whisperer @object_name, method,
|
37
|
+
def whisperer(method, template, field_attrs={})
|
38
|
+
@template.assoc_whisperer @object_name, method, template, objectify_options(field_attrs)
|
64
39
|
end
|
65
40
|
end
|
66
41
|
|
@@ -3,20 +3,20 @@ module ActionView
|
|
3
3
|
module Tags # :nodoc:
|
4
4
|
class AssocWhispererField < Base # :nodoc:
|
5
5
|
|
6
|
-
def initialize(object_name, method_name, template_object,
|
7
|
-
|
8
|
-
options[:text_method] = AssocWhisperer.def_text_method unless options.has_key? :text_method
|
6
|
+
def initialize(object_name, method_name, template_object, whisp_template, options={})
|
7
|
+
@whisp_template = whisp_template
|
9
8
|
super object_name, method_name, template_object, options
|
10
|
-
@template = AssocWhisperer::Template.new action, @options
|
11
9
|
end
|
12
10
|
|
13
11
|
def render
|
14
|
-
|
15
|
-
|
16
|
-
contents
|
12
|
+
@whisp_template.value_text whispered_object
|
13
|
+
|
14
|
+
contents = @whisp_template.value_field_tag value_tag_id, value_tag_name
|
15
|
+
contents += @whisp_template.text_field_tag text_tag_id, text_tag_name, @options
|
16
|
+
contents += @whisp_template.dropdown_button_tag
|
17
17
|
|
18
18
|
content_tag :span, contents.html_safe, 'class' => 'assoc_whisperer',
|
19
|
-
'data-opts' => @
|
19
|
+
'data-opts' => @whisp_template.whisperer_settings.to_json
|
20
20
|
end
|
21
21
|
|
22
22
|
private
|
@@ -25,11 +25,6 @@ module ActionView
|
|
25
25
|
@whispered_object ||= value @object
|
26
26
|
end
|
27
27
|
|
28
|
-
def whispered_object_attribute(method)
|
29
|
-
wo = whispered_object
|
30
|
-
wo.send method if wo && wo.respond_to?(method)
|
31
|
-
end
|
32
|
-
|
33
28
|
def text_tag_name
|
34
29
|
"#{@object_name}[#{text_sanitized_method_name}]"
|
35
30
|
end
|
@@ -38,18 +33,8 @@ module ActionView
|
|
38
33
|
"#{sanitized_object_name}_#{text_sanitized_method_name}"
|
39
34
|
end
|
40
35
|
|
41
|
-
def text_tag_value
|
42
|
-
text = @template.opts[:text_method]
|
43
|
-
text = if text.respond_to? :call
|
44
|
-
text.call whispered_object
|
45
|
-
else
|
46
|
-
whispered_object_attribute(text)
|
47
|
-
end
|
48
|
-
ERB::Util.html_escape text
|
49
|
-
end
|
50
|
-
|
51
36
|
def text_sanitized_method_name
|
52
|
-
@text_sanitized_method_name ||= "#{@
|
37
|
+
@text_sanitized_method_name ||= "#{@whisp_template.opts[:name] || @method_name}_txt".sub(/\?$/,"")
|
53
38
|
end
|
54
39
|
|
55
40
|
def value_tag_name
|
@@ -60,18 +45,14 @@ module ActionView
|
|
60
45
|
"#{sanitized_object_name}_#{value_sanitized_method_name}"
|
61
46
|
end
|
62
47
|
|
63
|
-
def value_tag_value
|
64
|
-
whispered_object_attribute @template.opts[:value_method]
|
65
|
-
end
|
66
|
-
|
67
48
|
def value_sanitized_method_name
|
68
49
|
return @value_sanitized_method_name if defined? @value_sanitized_method_name
|
69
|
-
|
70
|
-
@
|
50
|
+
name = if @whisp_template.opts[:name]
|
51
|
+
@whisp_template.opts[:name].to_s
|
71
52
|
else
|
72
|
-
"#{@method_name}_#{@template.opts[:
|
53
|
+
"#{@method_name}_#{@template.opts[:value]}"
|
73
54
|
end
|
74
|
-
@value_sanitized_method_name =
|
55
|
+
@value_sanitized_method_name = name.sub(/\?$/, '')
|
75
56
|
end
|
76
57
|
|
77
58
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<%
|
2
2
|
text_method = local_assigns[:text] || :to_s
|
3
|
-
|
3
|
+
value_method = local_assigns[:value] || :id
|
4
4
|
%>
|
5
5
|
<div tabindex=0 class="list">
|
6
6
|
<% @objects.each do |o| %>
|
7
|
-
<div data-value="<%= o.send
|
7
|
+
<div data-value="<%= o.send value_method %>"><%= o.send text_method %></div>
|
8
8
|
<% end %>
|
9
9
|
</div>
|
@@ -2,47 +2,64 @@
|
|
2
2
|
|
3
3
|
module AssocWhisperer
|
4
4
|
class Template
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :opts
|
6
6
|
|
7
7
|
def initialize(action, opts={})
|
8
|
-
@action = action
|
8
|
+
@action = action[0]=='/' ? action : "#{AssocWhisperer.def_url}/#{action}"
|
9
9
|
@opts = opts
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def params(params)
|
13
|
+
@params = params
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def value_text(object_or_params, name=nil)
|
18
|
+
if object_or_params.is_a?(Hash) && name
|
19
|
+
@value = object_or_params[name]
|
20
|
+
@text = object_or_params["#{name}_txt"]
|
21
|
+
elsif object_or_params
|
22
|
+
value = @opts[:value] || AssocWhisperer.def_value
|
23
|
+
text = @opts[:text] || AssocWhisperer.def_text
|
24
|
+
@value = (object_or_params.send value if object_or_params.respond_to? value)
|
25
|
+
@text = (object_or_params.send text if object_or_params.respond_to? text)
|
26
|
+
else
|
27
|
+
@value = nil
|
28
|
+
@text = nil
|
29
|
+
end
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def tag_contents(input_name, field_attrs={})
|
13
34
|
input_name = input_name.to_s
|
14
35
|
sanitized_id = input_name.dup.delete(']').gsub(/[^-a-zA-Z0-9:.]/, "_")
|
15
36
|
text_tag_name = input_name.dup
|
16
37
|
text_tag_name.insert (text_tag_name[-1]==']' ? -2 : -1), '_txt'
|
17
38
|
|
18
|
-
contents = value_field_tag sanitized_id, input_name
|
19
|
-
contents += text_field_tag "#{sanitized_id}_txt", text_tag_name,
|
39
|
+
contents = value_field_tag sanitized_id, input_name
|
40
|
+
contents += text_field_tag "#{sanitized_id}_txt", text_tag_name, field_attrs
|
20
41
|
contents + dropdown_button_tag
|
21
42
|
end
|
22
43
|
|
23
|
-
def
|
24
|
-
h = {
|
25
|
-
h
|
26
|
-
h[:params] = @
|
44
|
+
def whisperer_settings
|
45
|
+
h = {action: @action}
|
46
|
+
# h[:cs] = @opts[:client_side] if @opts[:client_side]
|
47
|
+
h[:params] = @params if @params
|
27
48
|
h
|
28
49
|
end
|
29
50
|
|
30
|
-
def value_field_tag(id, name
|
31
|
-
%(<input type="hidden" id="#{id}" name="#{name}" value="#{value}" class="value_field">)
|
51
|
+
def value_field_tag(id, name)
|
52
|
+
%(<input type="hidden" id="#{id}" name="#{name}" value="#{@value}" class="value_field">)
|
32
53
|
end
|
33
54
|
|
34
|
-
def text_field_tag(id, name,
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
arr << %(#{k}="#{opts[k]}")
|
41
|
-
arr
|
42
|
-
end
|
43
|
-
opts = opts * ' '
|
55
|
+
def text_field_tag(id, name, attrs={})
|
56
|
+
attrs[:size] = 12 unless attrs.has_key? :size
|
57
|
+
keys_whitelist = (attrs.keys & [:size, :placeholder, :maxlength, :title])
|
58
|
+
attrs = keys_whitelist.inject [] do |arr, k|
|
59
|
+
arr << %(#{k}="#{attrs[k]}")
|
60
|
+
arr
|
44
61
|
end
|
45
|
-
%(<input type="text" autocomplete="off" id="#{id}" name="#{name}" value="#{
|
62
|
+
%(<input type="text" autocomplete="off" id="#{id}" name="#{name}" value="#{@text}" class="text_field#{' unfilled' unless @value}"#{attrs * ' '}>)
|
46
63
|
end
|
47
64
|
|
48
65
|
def dropdown_button_tag
|
data/lib/assoc_whisperer.rb
CHANGED
@@ -5,7 +5,7 @@ require 'assoc_whisperer/template'
|
|
5
5
|
module AssocWhisperer
|
6
6
|
|
7
7
|
class << self
|
8
|
-
attr_accessor :def_url, :
|
8
|
+
attr_accessor :def_url, :attach_assets, :def_value, :def_text
|
9
9
|
end
|
10
10
|
|
11
11
|
module Rails
|
@@ -13,23 +13,10 @@ module AssocWhisperer
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def self.value_field_html(id, name, value)
|
17
|
-
%(<input type="hidden" id="#{id}" name="#{name}" value="#{value}" class="value_field">)
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.text_field_html(id, name, value, unfilled=true, opts={})
|
21
|
-
opts = opts.keys.inject([]){|arr, k| arr << %(#{k}="#{opts[k]}"); arr }*' '
|
22
|
-
%(<input type="text" id="#{id}" name="#{name}" value="#{value} class="text_field#{' unfilled' if unfilled}"#{opts}>)
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.dropdown_button_html
|
26
|
-
@dropdown_button_html ||= "<span class=\"dropdown_button\">\u25BE</span>"
|
27
|
-
end
|
28
|
-
|
29
16
|
end
|
30
17
|
|
31
18
|
AssocWhisperer.def_url = '/whisp'
|
32
|
-
AssocWhisperer.
|
19
|
+
AssocWhisperer.attach_assets = :attach_whisperer_assets
|
33
20
|
|
34
|
-
AssocWhisperer.
|
35
|
-
AssocWhisperer.
|
21
|
+
AssocWhisperer.def_value = :id
|
22
|
+
AssocWhisperer.def_text = :to_s
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: assoc_whisperer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ondřej Želazko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|