attribute_pair_generator 1.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bac8f3031dcc068e105bf8f30c4cdc0e2008cf98
4
+ data.tar.gz: 2420640934192d3de205e99924aaab25eaab4286
5
+ SHA512:
6
+ metadata.gz: 2b3faef7021f6a4bf7d1ff40fe4762a53d9d9c5bb0145fa1ed964205576344faeecb4b209392dbc8ce6c6e685b198c541faf3bcdaec5c509de2bfb2c56a555e9
7
+ data.tar.gz: 6c46c0d9b9fa7af72f6494257031911b0e50c6439e181201430d4a2ab1c18c834d9c82477f0270d23a471a4eaf120c813cfb458769fb3d5ea042b3a2cedca341
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013, Andrew Thal, Jeff Whitmire, and Contributors. All Rights Reserved.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # Attribute Pair Generator
2
+
3
+ * Easily generate form fields and object information fields with labels.
4
+ * Maintain consistent form structure without lots of html overhead:
5
+
6
+ Using APG, this...
7
+
8
+ <% apg = AttributePairGenerator.new(foo) %>
9
+ <%= form_tag foo_path(foo.id), method: :put do -%>
10
+ <dl>
11
+ <%= apg.text_field(attr: :title, help: "the title of your foo") %>
12
+ <%= apg.date(attr: :starts_at) %>
13
+ <%= apg.plain_text(attr: :status) %>
14
+ </dl>
15
+ <% end %>
16
+
17
+ generates...
18
+
19
+ <form accept-charset="UTF-8" action="/foo" method="post">
20
+ <dl>
21
+ <dt>title</dt>
22
+ <dd>
23
+ <input id="title" name="title" type="text" value="bar">
24
+ <span class="help-inline">the title of your foo</span>
25
+ </dd>
26
+ <dt>starts at</dt>
27
+ <dd>
28
+ <input class="datepicker" id="starts_at" name="starts_at" type="text" value="2013-10-30 05:00:00 +0000">
29
+ <span class="help-inline"></span>
30
+ </dd>
31
+ <dt>status</dt>
32
+ <dd>
33
+ approved
34
+ <span class="help-inline"></span>
35
+ </dd>
36
+ </dl>
37
+ </form>
38
+
39
+ ## Installation
40
+
41
+ Add this line to your application's Gemfile:
42
+
43
+ gem 'attribute_pair_generator'
44
+
45
+ And then execute:
46
+
47
+ $ bundle
48
+
49
+ Or install it yourself as:
50
+
51
+ $ gem install attribute_pair_generator
52
+
53
+ ## Common Usage
54
+
55
+ ### Call any of the apg methods, and pass in a hash of options, common options include:
56
+
57
+ * *attr*: using this option alone, you get the label to be a humanized version of the attr, and the value to be the attr called on the initialized object (if it exists)
58
+ * *label*: override the label
59
+ * *value*: override the value
60
+ * *help*: help text shown after the value
61
+ * *field_options*: pass in options to the `content_tag` for the main desired element (e.g. <a> tag, input, textarea, checkbox)
62
+ * *dd_options*: pass in options to the `content_tag` for the dd (value)
63
+ * *prefix*: give a prefix to input elements' names and values
64
+ * *disabled*: disable the input element or link
65
+
66
+ ## Examples
67
+
68
+ ### link
69
+
70
+ apg.link(title: "foo", url: "http://example.com")
71
+
72
+ ### plain text
73
+
74
+ apg.plain_text(label: 'contract dates', value: date_field_range('contract', 'contract'))
75
+
76
+ ### date (can be used with jqueryui datepicker)
77
+
78
+ apg.date(attr: :starts_at)
79
+
80
+ ### select dropdown
81
+
82
+ apg.select(attr: :lead_editor, value: editor_id, collection: [["Tom", 0], ["Dick", 1], ["Harry", 2]])
83
+
84
+ ### checkbox
85
+
86
+ apg.checkbox(attr: :ops_complete, disabled: !can_mark_ops_complete?)
87
+
88
+ ### text field
89
+
90
+ apg.text_field(attr: :long_title)
91
+ apg.text_field(prefix: 'tax', attr: :id, value: '', disabled: true)
92
+
93
+ ### text area
94
+
95
+ apg.text_area(attr: :email_addresses, value: email_addresses.join("\n"), help: "Email addresses. One per line")
96
+
97
+ ### radio buttons
98
+
99
+ apg.radio(attr: :review_source, collection: [[nil, 'none'], 'Review Site'], dd_options: {class: 'horizontal-layout'})
100
+
101
+ ## Authors
102
+
103
+ * Andrew Thal <andrew.thal@livingsocial.com>
104
+ * Jeff Whitmire <jeff.whitmire@livingsocial.com>
105
+
106
+ ## License
107
+
108
+ Attribute Pair Generator is released under the [MIT License](http://www.opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "rake/testtask"
2
+
3
+ FileList["tasks/*.rake"].each { |task| load task }
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['spec/*_spec.rb']
8
+ end
9
+
10
+ task :default do
11
+ system("rspec -c")
12
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "attribute_pair_generator"
7
+ gem.version = "1.0.1"
8
+ gem.authors = ["Andrew Thal", "Jeff Whitmire"]
9
+ gem.email = "andrew.thal@livingsocial.com"
10
+ gem.description = %q{Easily generate form fields and object information fields with labels.}
11
+ gem.summary = %q{Easily generate form fields and object information fields with labels.}
12
+ gem.homepage = "https://github.com/livingsocial/attribute-pair-generator"
13
+
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.files = `git ls-files`.split("\n")
18
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_development_dependency 'rake'
22
+ gem.add_development_dependency "faker"
23
+ gem.add_development_dependency "rspec", '~> 2.0'
24
+ gem.add_development_dependency "nokogiri", '~> 1.6'
25
+ gem.add_dependency "actionpack", '>= 3.0.0'
26
+ end
@@ -0,0 +1,109 @@
1
+ class AttributePairGenerator
2
+ require 'action_view'
3
+ include ActionView::Helpers::UrlHelper
4
+ include ActionView::Helpers::FormOptionsHelper
5
+ include ActionView::Helpers::FormTagHelper
6
+
7
+ attr_accessor :output_buffer
8
+ attr_reader :obj
9
+
10
+ def initialize(init_obj = nil)
11
+ @obj = init_obj
12
+ end
13
+
14
+ def link(options)
15
+ content = link_to options[:title], options[:url], options[:field_options]
16
+ render(content, options)
17
+ end
18
+
19
+ def plain_text(options)
20
+ render(value(options), options)
21
+ end
22
+
23
+ def date(options)
24
+ text_field_options = field_options(options)
25
+ ((text_field_options[:class] ||= '') << ' datepicker').strip!
26
+
27
+ content = text_field_tag attribute(options), value(options), text_field_options
28
+ render(content, options)
29
+ end
30
+
31
+ def select(options)
32
+ content = select_tag attribute(options), options_for_select(options[:collection], value(options)), field_options(options, prompt: options[:prompt], include_blank: options[:include_blank])
33
+ render(content, options)
34
+ end
35
+
36
+ def checkbox(options)
37
+ hidden_tag = hidden_field_tag attribute(options), options[:unchecked_value].nil? ? false : options[:unchecked_value]
38
+ checked_value = options[:checked_value] || true
39
+ is_checked = value(options).to_s == checked_value.to_s
40
+ content = hidden_tag + check_box_tag(attribute(options), checked_value, is_checked, field_options(options))
41
+ render(content, options)
42
+ end
43
+
44
+ def text_field(options)
45
+ content = text_field_tag attribute(options), value(options), field_options(options)
46
+ render(content, options)
47
+ end
48
+
49
+ def text_area(options)
50
+ content = text_area_tag attribute(options), value(options), field_options(options)
51
+ render(content, options)
52
+ end
53
+
54
+ def radio(options)
55
+ content = content_tag :ol, class: 'unstyled' do
56
+ options[:collection].map do |element|
57
+ if element.is_a?(Array)
58
+ value = element[0]
59
+ label = element[1]
60
+ else
61
+ value = label = element
62
+ end
63
+ content_tag :li do
64
+ label_tag("#{attribute(options)}_#{value}", radio_button_tag(attribute(options), value || '', value == value(options), field_options(options)) + label, class: 'radio')
65
+ end
66
+ end.flatten.join("").html_safe
67
+ end
68
+
69
+ render(content, options)
70
+ end
71
+
72
+ private
73
+
74
+ def field_options(options, overrides={})
75
+ {disabled: options[:disabled], name: name(options)}.merge(overrides).merge(options.fetch(:field_options, {}))
76
+ end
77
+
78
+ def render(content, options)
79
+ dt_content = options[:label] ? options[:label].to_s : options[:attr].to_s.humanize.downcase
80
+ dd_content = content.to_s
81
+ dd_content += content_tag(:span, class: "help-inline") { options[:help].to_s } if options[:help]
82
+ content_tag(:dt) { dt_content } +
83
+ content_tag(:dd, options[:dd_options]) { dd_content.html_safe }
84
+ end
85
+
86
+ def value(options)
87
+ if options[:value]
88
+ options[:value]
89
+ elsif obj.respond_to?(options[:attr])
90
+ obj.send(options[:attr])
91
+ end
92
+ end
93
+
94
+ def name(options)
95
+ if options[:prefix]
96
+ "#{options[:prefix]}[#{options[:attr]}]"
97
+ else
98
+ options[:attr]
99
+ end
100
+ end
101
+
102
+ def attribute(options)
103
+ if options[:prefix]
104
+ "#{options[:prefix]}_#{options[:attr]}"
105
+ else
106
+ options[:attr]
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,469 @@
1
+ require 'spec_helper'
2
+
3
+ describe AttributePairGenerator do
4
+ let(:test_object) { double(id: 1, full_name: "foo bar", date: "2013-05-13", featured: true, scheduler: 2) }
5
+ let(:subject) { AttributePairGenerator.new(test_object) }
6
+ let(:generated) { Nokogiri::HTML(subject.send(generator_method, generator_arguments)) }
7
+
8
+ shared_examples 'a generated pair structure' do
9
+ it { generated.css('dt').should be_present }
10
+ it { generated.css('dd').should be_present }
11
+ end
12
+
13
+ shared_examples 'accepts standard options' do
14
+ context 'if given a help option' do
15
+ it 'creates a span with the help text' do
16
+ generator_arguments[:help] = Faker::Lorem.sentence
17
+ generated.css("dd span.help-inline").text.should eq(generator_arguments[:help])
18
+ end
19
+ end
20
+
21
+ context 'if no help text given' do
22
+ it 'creates an empty help text area' do
23
+ generator_arguments.keys.should_not include(:help)
24
+ generated.css("dd span.help-inline").text.should be_empty
25
+ end
26
+ end
27
+
28
+ context 'if given a label option' do
29
+ it 'uses the given label in the dt' do
30
+ generator_arguments[:label] = Faker::Lorem.word
31
+ generated.css("dt").text.should eq(generator_arguments[:label])
32
+ end
33
+ end
34
+
35
+ context 'if no label option given' do
36
+ it 'uses the attribute name for the label' do
37
+ generator_arguments.keys.should_not include(:label)
38
+ generated.css("dt").text.should eq(generator_arguments[:attr].to_s.humanize.downcase)
39
+ end
40
+ end
41
+
42
+ context "if given dd_options" do
43
+ let(:dd_options) { {class: 'special-fluffy-dd'} }
44
+ it "uses those options on the dd element" do
45
+ generator_arguments[:dd_options] = dd_options
46
+ generated.css("dd").first.attributes["class"].value.should match /#{dd_options[:class]}/
47
+ end
48
+ end
49
+ end
50
+
51
+ shared_examples 'form field prefix generator' do
52
+ context 'if a prefix option is given' do
53
+ before do
54
+ generator_arguments[:prefix] = 'foo'
55
+ end
56
+
57
+ it 'creates the id as prefix_attribute' do
58
+ generated.css('dd').children.last['id'].should == "#{generator_arguments[:prefix]}_#{generator_arguments[:attr]}"
59
+ end
60
+
61
+ it 'creates the name as prefix[attribute]' do
62
+ generated.css('dd').children.last['name'].should == "#{generator_arguments[:prefix]}[#{generator_arguments[:attr]}]"
63
+ end
64
+
65
+ it 'does not use the prefix in the label' do
66
+ generated.css("dt").text.should eq(generator_arguments[:attr].to_s.humanize.downcase)
67
+ end
68
+ end
69
+
70
+ context 'if not given a prefix option' do
71
+ before do
72
+ generator_arguments.keys.should_not include(:prefix)
73
+ end
74
+
75
+ it 'uses the attribute as the id' do
76
+ generated.css('dd').children.last['id'].should == generator_arguments[:attr].to_s
77
+ end
78
+
79
+ it 'uses the attribute as the name' do
80
+ generated.css('dd').children.last['id'].should == generator_arguments[:attr].to_s
81
+ end
82
+ end
83
+ end
84
+
85
+ shared_examples 'form field value generator' do
86
+ context 'if a value option is given' do
87
+ before do
88
+ generator_arguments[:value] = '7337'
89
+ end
90
+
91
+ it 'uses the value given in the params' do
92
+ node = generated.css('dd').children.first
93
+
94
+ if node.has_attribute?('value')
95
+ node['value'].should == generator_arguments[:value]
96
+ else
97
+ node.text.should match /#{generator_arguments[:value]}/
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ describe '#obj' do
104
+ its(:obj) { should eq(test_object) }
105
+ end
106
+
107
+ context 'information field generators' do
108
+ describe '#plain_text' do
109
+ let(:generator_method) { 'plain_text' }
110
+
111
+ context 'with basic options' do
112
+ let(:generator_arguments) { {attr: :id} }
113
+
114
+ it_should_behave_like 'a generated pair structure'
115
+ it_should_behave_like 'accepts standard options'
116
+
117
+ it 'renders plain text in the dd' do
118
+ generated.css("dd").text.should eq(test_object.id.to_s)
119
+ end
120
+ end
121
+ end
122
+
123
+ describe '#link' do
124
+ let(:generator_method) { 'link' }
125
+ let(:generator_arguments) { {title: "foo", url: "http://example.com"} }
126
+
127
+ context 'with basic options' do
128
+ it_should_behave_like 'a generated pair structure'
129
+ it_should_behave_like 'accepts standard options'
130
+
131
+ it 'renders a link in the dd' do
132
+ generated.css("dd").children.first.node_name.should == 'a'
133
+ end
134
+
135
+ it 'uses the title as the text of the link' do
136
+ generated.css("dd a").text.should eq("foo")
137
+ end
138
+
139
+ it 'uses the url as the target of the link' do
140
+ generated.css("dd a").first.attributes["href"].value.should eq("http://example.com")
141
+ end
142
+ end
143
+
144
+ context 'if given an extra field_options parameter' do
145
+ before do
146
+ generator_arguments[:field_options] = {class: 'findable_link'}
147
+ end
148
+
149
+ it 'sticks the extra options on the link element' do
150
+ generated.css("dd a").first.attributes["class"].value.should match /#{generator_arguments[:field_options][:class]}/
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ context 'form input generators' do
157
+ describe '#date' do
158
+ let(:generator_method) { 'date' }
159
+ let(:generator_arguments) { {attr: :date} }
160
+
161
+ context 'with basic options' do
162
+ it_should_behave_like 'a generated pair structure'
163
+ it_should_behave_like 'accepts standard options'
164
+ it_should_behave_like 'form field prefix generator'
165
+ it_should_behave_like 'form field value generator'
166
+
167
+ it 'renders an input element in the dd' do
168
+ generated.css("dd").children.first.node_name.should == 'input'
169
+ end
170
+
171
+ it 'rendered input element should have a text type' do
172
+ generated.css("dd input").first['type'].should match /text/
173
+ end
174
+
175
+ it 'adds the datepicker class to work with jquery-ui datepicker' do
176
+ generated.css("dd input").first['class'].should match /datepicker/
177
+ end
178
+ end
179
+
180
+ context 'with extra classes pass in field_options' do
181
+ before do
182
+ generator_arguments[:field_options] = {class: 'flibberty'}
183
+ end
184
+
185
+ it 'should have both expected classes instead of overwriting' do
186
+ generated.css("dd input").first['class'].should match /datepicker/
187
+ generated.css("dd input").first['class'].should match /#{generator_arguments[:field_options][:class]}/
188
+ end
189
+ end
190
+ end
191
+
192
+ describe '#select' do
193
+ let(:generator_method) { 'select' }
194
+ let(:generator_arguments) { {attr: :scheduler, collection: [[1, "Tom"], [2, "Dick"], [3, "Harry"]]} }
195
+
196
+ context 'with basic options' do
197
+ it_should_behave_like 'a generated pair structure'
198
+ it_should_behave_like 'accepts standard options'
199
+ #it_should_behave_like 'form field generator'
200
+
201
+ it 'renders a select element in the dd' do
202
+ generated.css("dd").children.first.node_name.should == 'select'
203
+ end
204
+
205
+ context 'without the include_blank or prompt options' do
206
+ it 'should not have a blank option element' do
207
+ generated.css("dd select option").any? { |option| option.text.blank? }.should be_false
208
+ end
209
+ end
210
+
211
+ context 'with the include_blank option' do
212
+ before do
213
+ generator_arguments[:include_blank] = true
214
+ end
215
+
216
+ it "includes a blank option first in the selector" do
217
+ generated.css("dd select option")[0].text.should be_blank
218
+ generated.css("dd select option")[0].attributes["value"].to_s.should be_blank
219
+ generated.css("dd select option")[0].attributes["selected"].should be_blank
220
+ end
221
+ end
222
+
223
+ context 'with the prompt option' do
224
+ let(:prompt) { 'Pick Me' }
225
+ before do
226
+ generator_arguments[:prompt] = prompt
227
+ end
228
+
229
+ it "includes a blank option first in the selector" do
230
+ generated.css("dd select option")[0].text.should == prompt
231
+ generated.css("dd select option")[0].attributes["value"].to_s.should be_blank
232
+ generated.css("dd select option")[0].attributes["selected"].should be_blank
233
+ end
234
+ end
235
+
236
+ context 'with just an array of strings as the collection' do
237
+ before do
238
+ generator_arguments[:collection] = %w(Tom Dick Harry)
239
+ end
240
+
241
+ it "generates the expected selector" do
242
+ generated.css("dd select option")[0].text.should eq("Tom")
243
+ generated.css("dd select option")[1].text.should eq("Dick")
244
+ generated.css("dd select option")[2].text.should eq("Harry")
245
+ end
246
+ end
247
+ end
248
+ end
249
+
250
+ describe '#text_field' do
251
+ let(:generator_method) { 'text_field' }
252
+
253
+ context 'with basic options' do
254
+ let(:generator_arguments) { {attr: :full_name} }
255
+
256
+ it_should_behave_like 'a generated pair structure'
257
+ it_should_behave_like 'accepts standard options'
258
+ it_should_behave_like 'form field prefix generator'
259
+ it_should_behave_like 'form field value generator'
260
+
261
+ it 'renders an input element in the dd' do
262
+ generated.css("dd").children.first.node_name.should == 'input'
263
+ end
264
+
265
+ it 'rendered input element should have a text type' do
266
+ generated.css("dd input").first['type'].should match /text/
267
+ end
268
+ end
269
+ end
270
+
271
+ describe '#text_area' do
272
+ let(:generator_method) { 'text_area' }
273
+
274
+ context 'with basic options' do
275
+ let(:generator_arguments) { {attr: :full_name} }
276
+
277
+ it_should_behave_like 'a generated pair structure'
278
+ it_should_behave_like 'accepts standard options'
279
+ it_should_behave_like 'form field prefix generator'
280
+ it_should_behave_like 'form field value generator'
281
+
282
+ it 'renders a textarea element in the dd' do
283
+ generated.css("dd").children.first.node_name.should == 'textarea'
284
+ end
285
+
286
+ it 'sets the value of the textarea to the attribute value' do
287
+ generated.css("dd textarea").text.should match /#{test_object.send(generator_arguments[:attr])}/
288
+ end
289
+ end
290
+ end
291
+
292
+ describe '#radio' do
293
+ let(:generator_method) { 'radio' }
294
+ context 'with basic options' do
295
+ let(:generator_arguments) { {attr: :scheduler, collection: [[1, "Tom"], [2, "Dick"], [3, "Harry"]]} }
296
+
297
+ it_should_behave_like 'a generated pair structure'
298
+ it_should_behave_like 'accepts standard options'
299
+ # can't use the shared example here, this generates a collection of form elements
300
+ #it_should_behave_like 'form field generator'
301
+
302
+ context 'if a prefix option is given' do
303
+ before do
304
+ generator_arguments[:prefix] = 'foo'
305
+ end
306
+
307
+ it 'creates the id as prefix_attribute' do
308
+ generated.css('dd input').each do |radio_element|
309
+ radio_element['id'].should match /^#{generator_arguments[:prefix]}_#{generator_arguments[:attr]}_\d$/
310
+ end
311
+ end
312
+
313
+ it 'creates the name as prefix[attribute]' do
314
+ generated.css('dd input').each do |radio_element|
315
+ radio_element['name'].should == "#{generator_arguments[:prefix]}[#{generator_arguments[:attr]}]"
316
+ end
317
+ end
318
+ end
319
+
320
+ context 'if given a one dimensional array for a collection' do
321
+ before do
322
+ generator_arguments[:collection] = %w(foo bar baz)
323
+ end
324
+
325
+ it 'should generate the same number of labels as the members of the collection' do
326
+ generated.css("dd label").size.should == generator_arguments[:collection].size
327
+ end
328
+
329
+ it 'should generate a label for each member of the collection' do
330
+ generated.css("dd label").collect(&:text).should == generator_arguments[:collection]
331
+ end
332
+
333
+ it 'should generate the same number of input elements as the members of the collection' do
334
+ generated.css("dd input").size.should == generator_arguments[:collection].size
335
+ end
336
+
337
+ it 'should set the input value for each member of the collection' do
338
+ generated.css("dd input").collect{|e| e.attr('value')}.should == generator_arguments[:collection]
339
+ end
340
+ end
341
+
342
+ context 'if not given a prefix option' do
343
+ before do
344
+ generator_arguments.keys.should_not include(:prefix)
345
+ end
346
+
347
+ it 'uses the attribute as the id' do
348
+ generated.css('dd input').each do |radio_element|
349
+ radio_element['id'].should match /^#{generator_arguments[:attr]}_\d$/
350
+ end
351
+ end
352
+
353
+ it 'uses the attribute as the name' do
354
+ generated.css('dd input').each do |radio_element|
355
+ radio_element['name'].should == generator_arguments[:attr].to_s
356
+ end
357
+ end
358
+ end
359
+
360
+ it 'should generate the same number of labels as the members of the collection' do
361
+ generated.css("dd label").size.should == generator_arguments[:collection].size
362
+ end
363
+
364
+ it 'should generate a label for each member of the collection' do
365
+ generated.css("dd label").collect(&:text).should == generator_arguments[:collection].collect { |m| m[1] }
366
+ end
367
+
368
+ it 'should generate the same number of input elements as the members of the collection' do
369
+ generated.css("dd input").size.should == generator_arguments[:collection].size
370
+ end
371
+
372
+ it 'builds a proper label' do
373
+ generator_arguments[:collection].each_with_index do |member, index|
374
+ generated.css("dd label")[index].attributes["for"].value.should eq("#{generator_arguments[:attr]}_#{member[0]}")
375
+ generated.css("dd label")[index].text.should eq(member[1])
376
+ end
377
+ end
378
+
379
+ it 'builds a proper radio button' do
380
+ generator_arguments[:collection].each_with_index do |member, index|
381
+ generated.css("dd input")[index].attributes["name"].value.should eq(generator_arguments[:attr].to_s)
382
+ generated.css("dd input")[index].attributes["value"].value.should eq(member[0].to_s)
383
+ end
384
+ end
385
+
386
+ it 'correctly sets the checked attribute and value based on the right value' do
387
+ generator_arguments[:collection].each_with_index do |member, index|
388
+ if test_object.send(generator_arguments[:attr]) == member[0]
389
+ generated.css("dd input")[index].attributes["checked"].value.should eq("checked")
390
+ else
391
+ generated.css("dd input")[index].should_not have_attribute("checked")
392
+ end
393
+ end
394
+ end
395
+ end
396
+ end
397
+
398
+ describe '#checkbox' do
399
+ let(:generator_method) { 'checkbox' }
400
+ let(:generator_arguments) { { attr: :featured } }
401
+
402
+ context 'with basic options' do
403
+ it_should_behave_like 'a generated pair structure'
404
+ it_should_behave_like 'accepts standard options'
405
+ it_should_behave_like 'form field prefix generator'
406
+
407
+ it 'renders a hidden input element in the dd' do
408
+ generated.css("dd").children.first.node_name.should == 'input'
409
+ generated.css("dd").children.first['type'].should match /hidden/
410
+ end
411
+
412
+ it 'renders a checkbox input element in the dd' do
413
+ generated.css("dd").children[1].node_name.should == 'input'
414
+ generated.css("dd").children[1]['type'].should match /checkbox/
415
+ end
416
+
417
+ it 'has a false hiden value' do
418
+ generated.css("dd input[type='hidden']").first['value'].should eq("false")
419
+ end
420
+
421
+ it 'can override a hidden value' do
422
+ generator_arguments[:unchecked_value] = "foo"
423
+ generated.css("dd input[type='hidden']").first['value'].should eq("foo")
424
+ end
425
+
426
+ context 'there is no explicitly set checked value' do
427
+ let(:generator_arguments) { { attr: :featured } }
428
+ it 'has a value of true' do
429
+ generated.css("dd input").last['value'].should eq("true")
430
+ end
431
+
432
+ context 'when the value is true' do
433
+ it 'sets the checked attribute' do
434
+ generated.css("dd input").last.should have_attribute("checked")
435
+ end
436
+ end
437
+
438
+ context 'when the value is not true' do
439
+ before { test_object.stub(:featured).and_return(false) }
440
+ it 'does not set the checked attribute' do
441
+ generated.css("dd input").last.should_not have_attribute("checked")
442
+ end
443
+ end
444
+ end
445
+
446
+ context 'a checked value is specified' do
447
+ let(:generator_arguments) { { attr: :featured, checked_value: 5 } }
448
+ it 'has a value of the checked value' do
449
+ generated.css("dd input").last['value'].should eq("5")
450
+ end
451
+
452
+ context 'when the value matches the checked_value' do
453
+ before { test_object.stub(:featured).and_return(generator_arguments[:checked_value]) }
454
+ it 'sets the checked attribute' do
455
+ generated.css("dd input").last.should have_attribute("checked")
456
+ end
457
+ end
458
+
459
+ context 'when the value does not matches the checked_value' do
460
+ before { test_object.stub(:featured).and_return(nil) }
461
+ it 'does not set the checked attribute' do
462
+ generated.css("dd input").last.should_not have_attribute("checked")
463
+ end
464
+ end
465
+ end
466
+ end
467
+ end
468
+ end
469
+ end
@@ -0,0 +1,6 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+ require 'rspec/autorun'
4
+ require "attribute_pair_generator"
5
+ require 'nokogiri'
6
+ require 'faker'
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: attribute_pair_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Thal
8
+ - Jeff Whitmire
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-11-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: faker
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: '2.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: '2.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: nokogiri
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '1.6'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.6'
70
+ - !ruby/object:Gem::Dependency
71
+ name: actionpack
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: 3.0.0
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: 3.0.0
84
+ description: Easily generate form fields and object information fields with labels.
85
+ email: andrew.thal@livingsocial.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .gitignore
91
+ - Gemfile
92
+ - MIT-LICENSE
93
+ - README.md
94
+ - Rakefile
95
+ - attribute_pair_generator.gemspec
96
+ - lib/attribute_pair_generator.rb
97
+ - spec/attribute_pair_generator_spec.rb
98
+ - spec/spec_helper.rb
99
+ homepage: https://github.com/livingsocial/attribute-pair-generator
100
+ licenses:
101
+ - MIT
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 2.0.3
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: Easily generate form fields and object information fields with labels.
123
+ test_files:
124
+ - spec/attribute_pair_generator_spec.rb
125
+ - spec/spec_helper.rb