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 +7 -0
- data/.gitignore +5 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +20 -0
- data/README.md +108 -0
- data/Rakefile +12 -0
- data/attribute_pair_generator.gemspec +26 -0
- data/lib/attribute_pair_generator.rb +109 -0
- data/spec/attribute_pair_generator_spec.rb +469 -0
- data/spec/spec_helper.rb +6 -0
- metadata +125 -0
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/Gemfile
ADDED
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,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
|
data/spec/spec_helper.rb
ADDED
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
|