hstore_radio_buttons 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +232 -0
- data/Rakefile +9 -0
- data/hstore_radio_buttons.gemspec +30 -0
- data/lib/generators/hstore_radio_buttons.rb +11 -0
- data/lib/generators/hstore_radio_buttons/migration/migration_generator.rb +16 -0
- data/lib/generators/hstore_radio_buttons/migration/templates/migration.rb +14 -0
- data/lib/hstore_radio_buttons.rb +39 -0
- data/lib/hstore_radio_buttons/button_options.rb +9 -0
- data/lib/hstore_radio_buttons/button_set.rb +32 -0
- data/lib/hstore_radio_buttons/configuration.rb +48 -0
- data/lib/hstore_radio_buttons/helpers/form_helper.rb +36 -0
- data/lib/hstore_radio_buttons/hstore_radio_data.rb +7 -0
- data/lib/hstore_radio_buttons/version.rb +3 -0
- data/test/lib/hstore_radio_buttons/button_options_test.rb +27 -0
- data/test/lib/hstore_radio_buttons/button_set_test.rb +58 -0
- data/test/lib/hstore_radio_buttons/configuration_test.rb +57 -0
- data/test/lib/hstore_radio_buttons/helpers/form_builder_test.rb +64 -0
- data/test/lib/hstore_radio_buttons/helpers/form_helper_test.rb +24 -0
- data/test/lib/hstore_radio_buttons/hstore_radio_buttons_test.rb +16 -0
- data/test/lib/hstore_radio_buttons/version_test.rb +7 -0
- data/test/support/config/hstore_radio_button_sets.yml +14 -0
- data/test/support/models.rb +6 -0
- data/test/support/schema.rb +23 -0
- data/test/test_helper.rb +18 -0
- metadata +175 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Ian Whitney
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,232 @@
|
|
1
|
+
# hstore_radio_buttons
|
2
|
+
|
3
|
+
So, you need a bunch of radio buttons on a form. But there's no particular reason for you to save each question in its own database field. And, even better, you have access to the Hstore data type in postgres. hstore_radio_buttons is the library you are looking for. Define a set of radio buttons, display them in your form and then gather them all up and save the data in an hstore field.
|
4
|
+
|
5
|
+
# Requirements
|
6
|
+
|
7
|
+
- Postgres. If you have the hstore extension enabled, great. If not, the
|
8
|
+
migration generated by this gem will turn it on.
|
9
|
+
- Rails 3 and the activerecord-postgres-hstore gem installed
|
10
|
+
|
11
|
+
This might work with Rails 4, which has native support for hstore, but I haven't tried that yet.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
gem 'hstore_radio_buttons'
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install hstore_radio_buttons
|
26
|
+
|
27
|
+
hstore_radio_buttons will save all of your hstores in a single table. To
|
28
|
+
generate that table, do:
|
29
|
+
|
30
|
+
$ rails generate hstore_radio_buttons:migration
|
31
|
+
$ rake db:migrate
|
32
|
+
|
33
|
+
The migration does two things:
|
34
|
+
|
35
|
+
1. Executes the command "CREATE EXTENSION IF NOT EXISTS hstore"
|
36
|
+
2. Creates a polymorphic table hstore_radio_data, which is where all the
|
37
|
+
persisted data will be saved.
|
38
|
+
|
39
|
+
If you don't need to set up the hstore extension, just remove that part
|
40
|
+
of the migration before running it.
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
For every collection of radio button questions, you'll need to define their set of values as well as a label for the set of buttons. Say you want something like this:
|
45
|
+
|
46
|
+
Gender:
|
47
|
+
o Male
|
48
|
+
o Female
|
49
|
+
o Other
|
50
|
+
|
51
|
+
Favorite Barn Animal:
|
52
|
+
o Cow
|
53
|
+
o Sheep
|
54
|
+
o Pig
|
55
|
+
|
56
|
+
### Defining buttons in a YAML file
|
57
|
+
|
58
|
+
In above example we have two sets of buttons, one for the Gender question and one for the Barn Animal question. By default, this yaml file is stored in `config/hstore_radio_button_sets.yml`. But you can override that and put the file elsewhere, if you want.
|
59
|
+
|
60
|
+
---
|
61
|
+
person:
|
62
|
+
gender:
|
63
|
+
- male
|
64
|
+
- female
|
65
|
+
- other
|
66
|
+
'favorite barn animal':
|
67
|
+
- cow
|
68
|
+
- sheep
|
69
|
+
- pig
|
70
|
+
|
71
|
+
The above defines two sets of buttons that can be used by the person model. For a model to generate/save radio button data, the set must be defined for the model.
|
72
|
+
|
73
|
+
Then set up your model so that it knows it has hstore_radio_buttons.
|
74
|
+
|
75
|
+
class Person < ActiveRecord::Base
|
76
|
+
include HstoreRadioButtons
|
77
|
+
|
78
|
+
hstore_radio_buttons
|
79
|
+
...
|
80
|
+
end
|
81
|
+
|
82
|
+
Changing the location of the file is done by passing in the path of your
|
83
|
+
configuration file:
|
84
|
+
|
85
|
+
class Person < ActiveRecord::Base
|
86
|
+
include HstoreRadioButtons
|
87
|
+
|
88
|
+
hstore_radio_buttons './config/yamls/person_hstore_buttons.yml'
|
89
|
+
...
|
90
|
+
end
|
91
|
+
|
92
|
+
### Defining buttons with macros in the model itself
|
93
|
+
|
94
|
+
Instead of using the yaml file, you can define your buttons macro-style
|
95
|
+
within the model itself.
|
96
|
+
|
97
|
+
class Report < ActiveRecord::Base
|
98
|
+
include HstoreRadioButtons
|
99
|
+
|
100
|
+
hstore_radio_button Hash['viewed' => ['true', 'false']]
|
101
|
+
hstore_radio_button Hash['written by' => %w(monkeys interns milton)]
|
102
|
+
end
|
103
|
+
|
104
|
+
### Getters, Setters, Security
|
105
|
+
|
106
|
+
Adding the button sets gives you getters and setters for those sets:
|
107
|
+
|
108
|
+
>> p = Person.find(1)
|
109
|
+
>> p.gender
|
110
|
+
=> 'female'
|
111
|
+
>> p.favorite_barn_animal
|
112
|
+
=> 'sheep'
|
113
|
+
>> p.favorite_barn_animal = 'pig'
|
114
|
+
=> 'pig'
|
115
|
+
|
116
|
+
Keep in mind that the returned data will always be strings. So boolean
|
117
|
+
values aren't true and false, they are 'true' and 'false'. That's just
|
118
|
+
how hstore works.
|
119
|
+
|
120
|
+
And, for the sake of security, you can't set a value to
|
121
|
+
something that's not in your button definition. So if someone changes their
|
122
|
+
form submission values to include malicious data that should not be a
|
123
|
+
problem.<sup>*</sup>
|
124
|
+
|
125
|
+
|
126
|
+
>> p = Person.find(1)
|
127
|
+
>> p.gender = 'something hackerish'
|
128
|
+
>> p.gender = nil
|
129
|
+
|
130
|
+
<sup>*</sup> Notice the 'should' part there. I am not a security expert
|
131
|
+
and I welcome any pull requests that make this gem more secure.
|
132
|
+
|
133
|
+
Validations from ActiveModel work as well. So you can do:
|
134
|
+
|
135
|
+
class Person < ActiveRecord::Base
|
136
|
+
...
|
137
|
+
validates_presence_of :gender
|
138
|
+
end
|
139
|
+
|
140
|
+
Or whatever other validations you need.
|
141
|
+
|
142
|
+
### Displaying buttons in a form
|
143
|
+
|
144
|
+
To display the radio button set on the form, you have three options:
|
145
|
+
|
146
|
+
1. Use a helper to display a single radio button
|
147
|
+
2. Use a helper to display all the radio buttons
|
148
|
+
3. Use the Rails form helpers
|
149
|
+
|
150
|
+
#### Use a helper to display a single radio button
|
151
|
+
|
152
|
+
<%= form_for @person do |f|>
|
153
|
+
<%= f.hstore_radio_button('gender') %>
|
154
|
+
...
|
155
|
+
<%= f.hstore_radio_button('favorite barn animal') %>
|
156
|
+
<% end %>
|
157
|
+
|
158
|
+
#### Use a helper to display all the radio buttons
|
159
|
+
|
160
|
+
<%= form_for @person do |f|>
|
161
|
+
<%= f.hstore_radio_buttons %>
|
162
|
+
<% end %>
|
163
|
+
|
164
|
+
#### Use the Rails form helpers:
|
165
|
+
|
166
|
+
<%= form_for @person do |f|>
|
167
|
+
<%= f.label(:gender) %>
|
168
|
+
<%= f.radio_button(:gender, 'male') %>
|
169
|
+
<%= f.label(:gender, "Male", :value => 'male') %>
|
170
|
+
...etc...
|
171
|
+
<% end %>
|
172
|
+
|
173
|
+
If you want to avoid the duplication that the above introduces, you can
|
174
|
+
use the _options method that is added to your model:
|
175
|
+
|
176
|
+
<%= form_for @person do |f|>
|
177
|
+
<%= f.label(:gender) %>
|
178
|
+
<% @person.gender_options.each do |option| %>
|
179
|
+
<%= f.radio_button(:gender, option) %>
|
180
|
+
<%= f.label(:gender, option.titleize, :value => option) %>
|
181
|
+
<% end %>
|
182
|
+
<% end %>
|
183
|
+
|
184
|
+
### Controlling helper-created output
|
185
|
+
|
186
|
+
By default the `hstore_radio_button` or `hstore_radio_buttons` helpers
|
187
|
+
will give you output like this:
|
188
|
+
|
189
|
+
<div>
|
190
|
+
<label for='person_gender'>Gender</label><br />
|
191
|
+
<input id='person_gender_male' name 'person[gender]' type='radio'
|
192
|
+
value='male'>
|
193
|
+
<label for='person_gender_male'>Male</label><br />
|
194
|
+
</div>
|
195
|
+
|
196
|
+
You can swap those `<br />` tags for a different separator by passing in
|
197
|
+
your own:
|
198
|
+
|
199
|
+
<%= f.hstore_radio_button('gender', separator: " - " %>
|
200
|
+
|
201
|
+
If you need more control, you should probably just use the Rails helpers
|
202
|
+
approach.
|
203
|
+
|
204
|
+
### Persistence
|
205
|
+
|
206
|
+
The conversion of your data into an hstore is handled by
|
207
|
+
[activerecord-postgres-store]
|
208
|
+
(https://github.com/engageis/activerecord-postgres-hstore) so refer to
|
209
|
+
their documentation.
|
210
|
+
|
211
|
+
Your data will be stored in the hstore_radio_data table. If you saved
|
212
|
+
data for a Person with the id of 1, it will be saved as
|
213
|
+
|
214
|
+
model_id model_type hstore_data
|
215
|
+
1 Person {'gender' => 'other'....}
|
216
|
+
|
217
|
+
But it's easiest to just work with the getters and setters in the Person
|
218
|
+
model than dealing directly with this table.
|
219
|
+
|
220
|
+
And, of course, this perisisted data is used to mark the correct radio
|
221
|
+
buttons as 'selected' when the form is loaded later.
|
222
|
+
|
223
|
+
TODO: It'd be nice to have default values for a set.
|
224
|
+
TODO: Formtastic integration
|
225
|
+
|
226
|
+
## Contributing
|
227
|
+
|
228
|
+
1. Fork it
|
229
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
230
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
231
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
232
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hstore_radio_buttons/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "hstore_radio_buttons"
|
8
|
+
spec.version = HstoreRadioButtons::VERSION
|
9
|
+
spec.authors = ["Ian Whitney"]
|
10
|
+
spec.email = ["ian@ianwhitney.com"]
|
11
|
+
spec.description = %q{Works with postgres's hstore data type and Rails to let you display/store a collection of radio buttons in an hstore field}
|
12
|
+
spec.summary = %q{Define a set of radio buttons for a model and then save the perisisted data for these buttons in an hstore field. Good for data that you want to persist, but that isn't important enough for its own field in the model.}
|
13
|
+
spec.homepage = "https://github.com/IanWhitney/hstore_radio_buttons"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'activerecord', '~> 3.0'
|
22
|
+
spec.add_dependency 'activesupport', '~> 3.0'
|
23
|
+
spec.add_dependency 'actionpack', '~> 3.0'
|
24
|
+
spec.add_dependency 'activerecord-postgres-hstore'
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
spec.add_development_dependency "sqlite3"
|
29
|
+
spec.add_development_dependency "mocha"
|
30
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rails/generators/named_base'
|
2
|
+
|
3
|
+
module HstoreRadioButtons
|
4
|
+
module Generators
|
5
|
+
module Base
|
6
|
+
def source_root
|
7
|
+
@_hstore_radio_buttons_source_root ||= File.expand_path(File.join('../hstore_radio_buttons', generator_name, 'templates'), __FILE__)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'generators/hstore_radio_buttons'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module HstoreRadioButtons
|
5
|
+
module Generators
|
6
|
+
class MigrationGenerator < ActiveRecord::Generators::Base
|
7
|
+
extend Base
|
8
|
+
|
9
|
+
argument :name, :type => :string, :default => 'create_hstore_radio_data'
|
10
|
+
|
11
|
+
def generate_files
|
12
|
+
migration_template 'migration.rb', "db/migrate/#{name}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateHstoreRadioData < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :hstore_radio_data do |t|
|
4
|
+
t.belongs_to :model, :polymorphic => true
|
5
|
+
t.hstore :hstore_data
|
6
|
+
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.down
|
12
|
+
drop_table :hstore_radio_data
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
require 'active_support/concern'
|
3
|
+
require 'active_support/dependencies/autoload'
|
4
|
+
|
5
|
+
require 'hstore_radio_buttons/version'
|
6
|
+
require 'hstore_radio_buttons/configuration'
|
7
|
+
require 'hstore_radio_buttons/button_options'
|
8
|
+
require 'hstore_radio_buttons/button_set'
|
9
|
+
require 'hstore_radio_buttons/helpers/form_helper'
|
10
|
+
|
11
|
+
module HstoreRadioButtons
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
extend ActiveSupport::Autoload
|
14
|
+
|
15
|
+
autoload :HstoreRadioData
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def hstore_radio_buttons(yaml_file_location = './config/hstore_radio_button_sets.yml')
|
19
|
+
HstoreRadioButtons::Configuration.from_yaml(self,yaml_file_location)
|
20
|
+
end
|
21
|
+
|
22
|
+
def hstore_radio_button(button_hash)
|
23
|
+
HstoreRadioButtons::Configuration.from_hash(self, button_hash)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def hstore_data_proxy
|
28
|
+
if self.hstore_radio_data.nil?
|
29
|
+
self.build_hstore_radio_data.hstore_data
|
30
|
+
else
|
31
|
+
self.hstore_radio_data.hstore_data
|
32
|
+
end
|
33
|
+
end
|
34
|
+
private :hstore_data_proxy
|
35
|
+
|
36
|
+
included do
|
37
|
+
has_one :hstore_radio_data, :class_name => 'HstoreRadioButtons::HstoreRadioData', :as => :model
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module HstoreRadioButtons
|
2
|
+
class ButtonSet
|
3
|
+
def initialize(button_definition, model)
|
4
|
+
setter_method = "#{button_definition.name}=".to_sym
|
5
|
+
getter_method = button_definition.name.to_sym
|
6
|
+
options_method = "#{button_definition.name}_options".to_sym
|
7
|
+
|
8
|
+
model.send(:define_method, getter_method) {
|
9
|
+
hstore_data_proxy[button_definition.name]
|
10
|
+
}
|
11
|
+
|
12
|
+
model.send(:define_method, setter_method) {|value|
|
13
|
+
if self.send(options_method).include?(value)
|
14
|
+
hstore_data_proxy[button_definition.name] = value
|
15
|
+
else
|
16
|
+
hstore_data_proxy[button_definition.name] = nil
|
17
|
+
end
|
18
|
+
}
|
19
|
+
|
20
|
+
model.send(:define_method, options_method) {
|
21
|
+
button_definition.options
|
22
|
+
}
|
23
|
+
|
24
|
+
if !model.instance_variable_defined?(:@hstore_button_names)
|
25
|
+
model.instance_variable_set(:@hstore_button_names, Set.new)
|
26
|
+
end
|
27
|
+
all_buttons_on_model = model.send(:instance_variable_get, :@hstore_button_names)
|
28
|
+
|
29
|
+
model.send(:instance_variable_set, :@hstore_button_names, all_buttons_on_model << button_definition.name.to_sym)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module HstoreRadioButtons
|
2
|
+
class Configuration
|
3
|
+
def self.from_yaml(model, yaml_file_location = './config/hstore_radio_button_sets.yml')
|
4
|
+
self.new._from_yaml(model, yaml_file_location)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.from_hash(model, raw_button_options)
|
8
|
+
self.new._from_hash(model, raw_button_options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def _from_yaml(model, yaml_file_location)
|
12
|
+
self.yaml_file_location = yaml_file_location
|
13
|
+
self.model = model
|
14
|
+
|
15
|
+
if yaml_exists?
|
16
|
+
button_options_from_yaml.each {|button_options| HstoreRadioButtons::ButtonSet.new(button_options,model)}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def _from_hash(model, raw_button_options)
|
21
|
+
self.model = model
|
22
|
+
button_options = button_options_from_raw(raw_button_options)
|
23
|
+
HstoreRadioButtons::ButtonSet.new(button_options,model)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
attr_accessor :model, :yaml_file_location
|
28
|
+
def config_file
|
29
|
+
File.open(yaml_file_location)
|
30
|
+
end
|
31
|
+
|
32
|
+
def yaml_exists?
|
33
|
+
File.exists?(yaml_file_location)
|
34
|
+
end
|
35
|
+
|
36
|
+
def button_options_from_yaml
|
37
|
+
button_options = []
|
38
|
+
YAML.load(config_file)[model.to_s.downcase].each do |key, value|
|
39
|
+
button_options << button_options_from_raw(Hash[key,value])
|
40
|
+
end
|
41
|
+
button_options
|
42
|
+
end
|
43
|
+
|
44
|
+
def button_options_from_raw(raw_button_options)
|
45
|
+
ButtonOptions.new(raw_button_options.keys.first, raw_button_options.values.first)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
|
3
|
+
module HstoreRadioButtons::FormHelper
|
4
|
+
def hstore_radio_button(object_name, method, tag_value, options = {})
|
5
|
+
separator = options.delete(:separator)
|
6
|
+
label = label(object_name, tag_value, options)
|
7
|
+
input = radio_button(object_name, method, tag_value, options)
|
8
|
+
"#{input}#{label}#{separator}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module HstoreRadioButtons::FormBuilder
|
13
|
+
include ActionView::Helpers::TagHelper
|
14
|
+
|
15
|
+
def hstore_radio_button(method, options = {})
|
16
|
+
options[:separator] = (options[:separator] ? options[:separator] : "<br />")
|
17
|
+
radio_options = object.public_send("#{method}_options".to_sym)
|
18
|
+
button_set = "#{method.to_s.titleize}#{options[:separator]}"
|
19
|
+
radio_options.each do |radio_option|
|
20
|
+
button_set += @template.hstore_radio_button(@object_name, method, radio_option, objectify_options(options))
|
21
|
+
end
|
22
|
+
content_tag(:div, button_set.html_safe).html_safe
|
23
|
+
end
|
24
|
+
|
25
|
+
def hstore_radio_buttons(options = {})
|
26
|
+
all_buttons = ""
|
27
|
+
object.class.instance_variable_get(:@hstore_button_names).each do |method|
|
28
|
+
all_buttons += hstore_radio_button(method, options)
|
29
|
+
end
|
30
|
+
all_buttons.html_safe
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
ActionView::Helpers::FormHelper.send(:include, HstoreRadioButtons::FormHelper)
|
35
|
+
ActionView::Base.send(:include, HstoreRadioButtons::FormHelper)
|
36
|
+
ActionView::Helpers::FormBuilder.send(:include, HstoreRadioButtons::FormBuilder)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative '../../test_helper.rb'
|
2
|
+
|
3
|
+
describe HstoreRadioButtons::ButtonOptions do
|
4
|
+
describe "#name" do
|
5
|
+
it "replaces spaces in a name with underscores" do
|
6
|
+
it = HstoreRadioButtons::ButtonOptions.new('test name', nil)
|
7
|
+
it.name.must_equal 'test_name'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "downcases the name" do
|
11
|
+
it = HstoreRadioButtons::ButtonOptions.new('Test', nil)
|
12
|
+
it.name.must_equal 'test'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#options" do
|
17
|
+
it "turns a single option into an array" do
|
18
|
+
it = HstoreRadioButtons::ButtonOptions.new('test', 1)
|
19
|
+
it.options.must_equal [1]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "turns a null options into an array" do
|
23
|
+
it = HstoreRadioButtons::ButtonOptions.new('test', nil)
|
24
|
+
it.options.must_equal []
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative '../../test_helper.rb'
|
2
|
+
|
3
|
+
describe HstoreRadioButtons::ButtonSet do
|
4
|
+
describe '#initialize' do
|
5
|
+
before :each do
|
6
|
+
@test_yaml_file_location = './test/support/config/hstore_radio_button_sets.yml'
|
7
|
+
@it = Person.new
|
8
|
+
config = YAML.load(File.open(@test_yaml_file_location))
|
9
|
+
@raw_button_definitions = config[@it.class.to_s.downcase]
|
10
|
+
@button_definitions = []
|
11
|
+
|
12
|
+
@raw_button_definitions.each do |button_definition|
|
13
|
+
button_options = HstoreRadioButtons::ButtonOptions.new(button_definition[0],button_definition[1])
|
14
|
+
@button_definitions << button_options
|
15
|
+
HstoreRadioButtons::ButtonSet.new(button_options,@it.class)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'adds getters and setters for the button sets defined in the config file' do
|
20
|
+
@button_definitions.each do |button_definition|
|
21
|
+
@it.must_respond_to button_definition.name.to_sym
|
22
|
+
@it.must_respond_to "#{button_definition.name}=".to_sym
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "adds a method that returns the button set's options" do
|
27
|
+
@button_definitions.each do |button_definition|
|
28
|
+
@it.must_respond_to "#{button_definition.name}_options".to_sym
|
29
|
+
@it.send("#{button_definition.name}_options".to_sym).must_equal button_definition.options
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "defines the setter so that a value not in the set's option is not passed to the hstore" do
|
34
|
+
bad_value = "hackery_nonsense"
|
35
|
+
@button_definitions.each do |button_definition|
|
36
|
+
@it.send("#{button_definition.name}=".to_sym, bad_value)
|
37
|
+
@it.send(button_definition.name.to_sym).must_be_nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'persists data sent to setters' do
|
42
|
+
@button_definitions.each do |button_definition|
|
43
|
+
random_value = button_definition.options.sample
|
44
|
+
@it.send("#{button_definition.name}=".to_sym, random_value)
|
45
|
+
@it.send(button_definition.name.to_sym).must_equal random_value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'allows the use of ActiveModel validation methods' do
|
50
|
+
@it.class.validates_presence_of(@button_definitions.sample.name)
|
51
|
+
@it.valid?.must_equal false
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'creates a class instance variable that returns the names of all hstore button names' do
|
55
|
+
@it.class.instance_variable_get(:@hstore_button_names).must_equal @button_definitions.map {|d| d.name.to_sym}.to_set
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative '../../test_helper.rb'
|
2
|
+
|
3
|
+
describe HstoreRadioButtons::Configuration do
|
4
|
+
|
5
|
+
describe "#from_yaml" do
|
6
|
+
before :each do
|
7
|
+
@test_yaml_file_location = './test/support/config/hstore_radio_button_sets.yml'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "checks if a provided yaml file exists" do
|
11
|
+
File.expects(:exists?).with(@test_yaml_file_location).returns(true)
|
12
|
+
HstoreRadioButtons::Configuration.from_yaml(Person, @test_yaml_file_location)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "checks if the default yaml file exists if none provided" do
|
16
|
+
yaml_file_location = './config/hstore_radio_button_sets.yml'
|
17
|
+
File.expects(:exists?).with(yaml_file_location).returns(false)
|
18
|
+
HstoreRadioButtons::Configuration.from_yaml(Person, yaml_file_location)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "has a yaml file to use" do
|
22
|
+
before :each do
|
23
|
+
@it = Person.new
|
24
|
+
config = YAML.load(File.open(@test_yaml_file_location))
|
25
|
+
@button_sets = config[@it.class.to_s.downcase]
|
26
|
+
@button_option_double = HstoreRadioButtons::ButtonOptions.new('test',[])
|
27
|
+
HstoreRadioButtons::ButtonOptions.stubs(:new).returns(@button_option_double)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'creates a button_set for each button set defined in the config file' do
|
31
|
+
@button_sets.each do |button_set|
|
32
|
+
HstoreRadioButtons::ButtonSet.expects(:new).with(@button_option_double,@it.class).returns(nil)
|
33
|
+
end
|
34
|
+
HstoreRadioButtons::Configuration.from_yaml(Person, @test_yaml_file_location)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#from_hash" do
|
40
|
+
describe "accepts a model and a button-defining hash to create a button" do
|
41
|
+
it "creates a button_set for each button defined by a hstore_radio_button macro" do
|
42
|
+
class Report < ActiveRecord::Base; end
|
43
|
+
@button_option_double = HstoreRadioButtons::ButtonOptions.new('test',[])
|
44
|
+
HstoreRadioButtons::ButtonOptions.stubs(:new).returns(@button_option_double)
|
45
|
+
|
46
|
+
HstoreRadioButtons::ButtonSet.expects(:new).with(@button_option_double,Report).twice.returns(nil)
|
47
|
+
|
48
|
+
class Report < ActiveRecord::Base
|
49
|
+
include HstoreRadioButtons
|
50
|
+
|
51
|
+
hstore_radio_button Hash['viewed' => ['true', 'false']]
|
52
|
+
hstore_radio_button Hash['written by' => %w(monkeys interns milton)]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require_relative '../../../test_helper.rb'
|
2
|
+
require 'action_view/test_case'
|
3
|
+
|
4
|
+
class FormBuilderTest < ActionView::TestCase
|
5
|
+
include ActiveSupport::Testing::SetupAndTeardown
|
6
|
+
include ActionView::TestCase::Behavior
|
7
|
+
|
8
|
+
setup do
|
9
|
+
@person_instance = Person.new
|
10
|
+
end
|
11
|
+
|
12
|
+
test "adds my FormHelper to Rails' FormHelper" do
|
13
|
+
assert ActionView::Helpers::FormBuilder.include?(HstoreRadioButtons::FormBuilder)
|
14
|
+
end
|
15
|
+
|
16
|
+
test "FormBuilder instances can respond to hstore_radio_button" do
|
17
|
+
it = ActionView::Helpers::FormBuilder.new(:person, @person_instance, view, {}, proc {})
|
18
|
+
assert it.respond_to?(:hstore_radio_button)
|
19
|
+
end
|
20
|
+
|
21
|
+
test "FormBuilder#hstore_radio_button wraps the whole thing in a div" do
|
22
|
+
view.stubs(:hstore_radio_button).with(any_parameters).returns("")
|
23
|
+
it = ActionView::Helpers::FormBuilder.new(:person, @person_instance, view, {}, proc {})
|
24
|
+
assert_match /^<div>/, it.hstore_radio_button(:gender)
|
25
|
+
assert_match /<\/div>$/, it.hstore_radio_button(:gender)
|
26
|
+
end
|
27
|
+
|
28
|
+
test "FormBuilder#hstore_radio_button returns a set of buttons that are prefaced with the button set's name" do
|
29
|
+
view.stubs(:hstore_radio_button).with(any_parameters).returns("")
|
30
|
+
it = ActionView::Helpers::FormBuilder.new(:person, @person_instance, view, {}, proc {})
|
31
|
+
assert_match /^<div>Gender/, it.hstore_radio_button(:gender)
|
32
|
+
end
|
33
|
+
|
34
|
+
test "#hstore_radio_button accepts a separator, which will be used to separate the button-set header from the buttons" do
|
35
|
+
view.stubs(:hstore_radio_button).with(any_parameters).returns("")
|
36
|
+
it = ActionView::Helpers::FormBuilder.new(:person, @person_instance, view, {}, proc {})
|
37
|
+
assert_match /^<div>Gender-/, it.hstore_radio_button(:gender, separator: "-")
|
38
|
+
end
|
39
|
+
|
40
|
+
test "FormBuilder#hstore_radio_button gets a button from FormHelper for each value in the _options method" do
|
41
|
+
expected = "<div>Gender<br />"
|
42
|
+
@person_instance.gender_options.each do |option|
|
43
|
+
view.stubs(:hstore_radio_button).with(:person, :gender, option, {:separator => "<br />", :object => @person_instance}).returns(option)
|
44
|
+
expected += "#{option}"
|
45
|
+
end
|
46
|
+
expected += "</div>"
|
47
|
+
|
48
|
+
it = ActionView::Helpers::FormBuilder.new(:person, @person_instance, view, {}, proc {})
|
49
|
+
|
50
|
+
assert_equal expected, it.hstore_radio_button(:gender)
|
51
|
+
end
|
52
|
+
|
53
|
+
test "#hstore_radio_buttons builds a button set for each button defined in the class" do
|
54
|
+
it = ActionView::Helpers::FormBuilder.new(:person, @person_instance, view, {}, proc {})
|
55
|
+
|
56
|
+
all_buttons = Person.instance_variable_get(:@hstore_button_names)
|
57
|
+
expected = ""
|
58
|
+
all_buttons.each do |b|
|
59
|
+
expected += it.hstore_radio_button(b)
|
60
|
+
end
|
61
|
+
|
62
|
+
assert_equal expected, it.hstore_radio_buttons
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative '../../../test_helper.rb'
|
2
|
+
require 'action_view/test_case'
|
3
|
+
|
4
|
+
class FormHelperTest < ActionView::TestCase
|
5
|
+
include ActionView::TestCase::Behavior
|
6
|
+
|
7
|
+
test "adds my FormHelper to Rails' FormHelper" do
|
8
|
+
assert ActionView::Helpers::FormHelper.include?(HstoreRadioButtons::FormHelper)
|
9
|
+
assert ActionView::Base.include?(HstoreRadioButtons::FormHelper)
|
10
|
+
end
|
11
|
+
|
12
|
+
test "view can respond to hstore_radio_button" do
|
13
|
+
assert view.respond_to?(:hstore_radio_button)
|
14
|
+
end
|
15
|
+
|
16
|
+
test "returns a radio input, label and separator of <br />" do
|
17
|
+
it = view.hstore_radio_button(:person, :gender, 'male', separator: "<br />")
|
18
|
+
expected = ""
|
19
|
+
expected += view.radio_button(:person, :gender, 'male', {})
|
20
|
+
expected += view.label(:person, 'male', {})
|
21
|
+
expected += "<br />"
|
22
|
+
assert_equal expected, it
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative '../../test_helper.rb'
|
2
|
+
|
3
|
+
describe HstoreRadioButtons do
|
4
|
+
it 'adds a HstoreRadioData active record class' do
|
5
|
+
HstoreRadioButtons::HstoreRadioData.new.wont_be_nil
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'allows a class to respond to hstore_radio_buttons' do
|
9
|
+
Person.must_respond_to :hstore_radio_buttons
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'builds a has_one association with the hstore_radio_data table' do
|
13
|
+
Person.new.must_respond_to :hstore_radio_data
|
14
|
+
Person.new.must_respond_to :build_hstore_radio_data
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
ActiveRecord::Base.establish_connection(
|
2
|
+
:adapter => 'sqlite3',
|
3
|
+
:database => File.expand_path('../../test.db', __FILE__)
|
4
|
+
)
|
5
|
+
|
6
|
+
class CreateSchema < ActiveRecord::Migration
|
7
|
+
def self.up
|
8
|
+
create_table :people, :force => true do |t|
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
|
12
|
+
create_table :reports, :force => true do |t|
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table :hstore_radio_data, :force => true do |t|
|
17
|
+
t.belongs_to :model, :polymorphic => true
|
18
|
+
t.text :hstore_data
|
19
|
+
|
20
|
+
t.timestamps
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
lib = File.expand_path('../../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
require 'hstore_radio_buttons'
|
5
|
+
|
6
|
+
require 'minitest/autorun'
|
7
|
+
require 'mocha/setup'
|
8
|
+
|
9
|
+
require 'fileutils'
|
10
|
+
require 'active_record'
|
11
|
+
require_relative 'support/models.rb'
|
12
|
+
require_relative 'support/schema.rb'
|
13
|
+
|
14
|
+
CreateSchema.suppress_messages{ CreateSchema.migrate(:up) }
|
15
|
+
|
16
|
+
MiniTest::Unit.after_tests do
|
17
|
+
FileUtils.rm_rf(File.expand_path('../test.db', __FILE__))
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hstore_radio_buttons
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ian Whitney
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: &70257637365360 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70257637365360
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activesupport
|
27
|
+
requirement: &70257637364800 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70257637364800
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: actionpack
|
38
|
+
requirement: &70257637364220 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '3.0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70257637364220
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: activerecord-postgres-hstore
|
49
|
+
requirement: &70257637363740 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70257637363740
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: bundler
|
60
|
+
requirement: &70257637363060 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '1.3'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70257637363060
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: &70257637362480 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70257637362480
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: sqlite3
|
82
|
+
requirement: &70257637361800 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70257637361800
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: mocha
|
93
|
+
requirement: &70257637361240 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70257637361240
|
102
|
+
description: Works with postgres's hstore data type and Rails to let you display/store
|
103
|
+
a collection of radio buttons in an hstore field
|
104
|
+
email:
|
105
|
+
- ian@ianwhitney.com
|
106
|
+
executables: []
|
107
|
+
extensions: []
|
108
|
+
extra_rdoc_files: []
|
109
|
+
files:
|
110
|
+
- .gitignore
|
111
|
+
- Gemfile
|
112
|
+
- LICENSE.txt
|
113
|
+
- README.md
|
114
|
+
- Rakefile
|
115
|
+
- hstore_radio_buttons.gemspec
|
116
|
+
- lib/generators/hstore_radio_buttons.rb
|
117
|
+
- lib/generators/hstore_radio_buttons/migration/migration_generator.rb
|
118
|
+
- lib/generators/hstore_radio_buttons/migration/templates/migration.rb
|
119
|
+
- lib/hstore_radio_buttons.rb
|
120
|
+
- lib/hstore_radio_buttons/button_options.rb
|
121
|
+
- lib/hstore_radio_buttons/button_set.rb
|
122
|
+
- lib/hstore_radio_buttons/configuration.rb
|
123
|
+
- lib/hstore_radio_buttons/helpers/form_helper.rb
|
124
|
+
- lib/hstore_radio_buttons/hstore_radio_data.rb
|
125
|
+
- lib/hstore_radio_buttons/version.rb
|
126
|
+
- test/lib/hstore_radio_buttons/button_options_test.rb
|
127
|
+
- test/lib/hstore_radio_buttons/button_set_test.rb
|
128
|
+
- test/lib/hstore_radio_buttons/configuration_test.rb
|
129
|
+
- test/lib/hstore_radio_buttons/helpers/form_builder_test.rb
|
130
|
+
- test/lib/hstore_radio_buttons/helpers/form_helper_test.rb
|
131
|
+
- test/lib/hstore_radio_buttons/hstore_radio_buttons_test.rb
|
132
|
+
- test/lib/hstore_radio_buttons/version_test.rb
|
133
|
+
- test/support/config/hstore_radio_button_sets.yml
|
134
|
+
- test/support/models.rb
|
135
|
+
- test/support/schema.rb
|
136
|
+
- test/test_helper.rb
|
137
|
+
homepage: https://github.com/IanWhitney/hstore_radio_buttons
|
138
|
+
licenses:
|
139
|
+
- MIT
|
140
|
+
post_install_message:
|
141
|
+
rdoc_options: []
|
142
|
+
require_paths:
|
143
|
+
- lib
|
144
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
153
|
+
- - ! '>='
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
requirements: []
|
157
|
+
rubyforge_project:
|
158
|
+
rubygems_version: 1.8.16
|
159
|
+
signing_key:
|
160
|
+
specification_version: 3
|
161
|
+
summary: Define a set of radio buttons for a model and then save the perisisted data
|
162
|
+
for these buttons in an hstore field. Good for data that you want to persist, but
|
163
|
+
that isn't important enough for its own field in the model.
|
164
|
+
test_files:
|
165
|
+
- test/lib/hstore_radio_buttons/button_options_test.rb
|
166
|
+
- test/lib/hstore_radio_buttons/button_set_test.rb
|
167
|
+
- test/lib/hstore_radio_buttons/configuration_test.rb
|
168
|
+
- test/lib/hstore_radio_buttons/helpers/form_builder_test.rb
|
169
|
+
- test/lib/hstore_radio_buttons/helpers/form_helper_test.rb
|
170
|
+
- test/lib/hstore_radio_buttons/hstore_radio_buttons_test.rb
|
171
|
+
- test/lib/hstore_radio_buttons/version_test.rb
|
172
|
+
- test/support/config/hstore_radio_button_sets.yml
|
173
|
+
- test/support/models.rb
|
174
|
+
- test/support/schema.rb
|
175
|
+
- test/test_helper.rb
|