simple_set 0.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: a89d5b1d434529dfd5e8496e9d3f6e276912068a
4
+ data.tar.gz: 431ecc28bbd8bf82a6ba765ab00e553ea6d77575
5
+ SHA512:
6
+ metadata.gz: 58858c8bf1379593972d5b39f9173dcfe463a3166646f798d4d17754b56649d64069e0049846681e44d920853ee7bfb07067558089ddc73234c9509e8245d308
7
+ data.tar.gz: b567de32fd5286e4730086673e495088a2463974fe3b45eaf71ab213fa48c8ce8080eddfe32a82f48bb277c02d3e6f20e88589b97bc9d196e950cc1145a3127b
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in simple_set.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 Sven Fuchs <svenfuchs@artweb-design.de>
2
+ Copyright (c) 2014 Romain Tartière <romain@blogreen.org>
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # SimpleSet
2
+
3
+ A Rails plugin which brings easy-to-use set-like functionality to ActiveRecord models.
4
+
5
+ This is based on [SimpleEnum](https://github.com/lwe/simple_enum).
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'simple_set'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install simple_set
20
+
21
+ ## Usage
22
+
23
+ Add this to a model:
24
+
25
+ class User < ActiveRecord::Base
26
+ as_set :roles, [:accounting, :management]
27
+ end
28
+
29
+ Then create the required `roles_cd` column using migrations:
30
+
31
+ class AddRolesToUsers < ActiveRecord::Migration
32
+ def change
33
+ add_column :users, :roles_cd, :integer
34
+ end
35
+ end
36
+
37
+ Now, it's possible to manage roles with maximum ease:
38
+
39
+ bob = User.new
40
+ bob.roles = [:accounting]
41
+ bob.accounting? #=> true
42
+ bob.management? #=> false
43
+ bob.roles #=> [:accounting]
44
+ bob.roles_cd #=> 1
45
+
46
+ ## Gotchas
47
+
48
+ 1. Acceptable values can be provided as an `Array` or as a `Hash`, the
49
+ following lines are equivalent:
50
+
51
+ as_set :spoken_languages, [:english, :french, :german, :japanese]
52
+ as_set :spoken_languages, {english: 1, french: 2, german: 4, japanese: 8}
53
+
54
+ Reordering the array will change each element's value which is likely
55
+ unwanted. Either only append new elements to the `Array` notation or use
56
+ the `Hash` notation.
57
+
58
+ 2. Although the `Hash` notation is less intuitive than the `Array` notation, it
59
+ allows some neat tricks:
60
+
61
+ class User
62
+ as_set :roles, {
63
+ management: 1,
64
+ accounting: 2,
65
+ human_resources: 4,
66
+
67
+ director: 7,
68
+ }
69
+ end
70
+
71
+ bob = User.create(roles: [:management, :accounting])
72
+ bob.director? #=> false
73
+ bob.human_resources = true
74
+ bob.director? #=> true
75
+
76
+ 3. If the shortcut methods (like `<symbol>?`, `<symbol>=` or `Klass.<symbol>`)
77
+ conflict with something in your class, it’s possible to define a prefix:
78
+
79
+ class Lp < ActiveRecord::Base
80
+ as_set :media_conditions, [:new, :sealed, :very_good, :good, :fair, :poor], prefix: true
81
+ end
82
+
83
+ Bug.media_condition_new #=> 1
84
+
85
+ When `:prefix` is set to `true`, shortcut methods are prefixed by the
86
+ _singularized name_ of the attribute.
87
+
88
+ The `:prefix` option not only takes a boolean value as an argument, but
89
+ instead can also be supplied a custom prefix (i.e. any string or symbol), so
90
+ with `prefix: 'foo'` all shortcut methods would look like: `foo_<symbol>...`
91
+
92
+ 4. Sometimes it might be useful to disable the generation of the shortcut
93
+ methods (`<symbol>?`, `<symbol>=` and `Klass.<symbol>`), to do so just add
94
+ the option `slim: true`:
95
+
96
+ class User
97
+ as_set :spoken_languages, [:english, :french, :german, :japanese], slim: true
98
+ end
99
+
100
+ bob = User.create(spoken_languages: [:english, :french]
101
+ bob.spoken_languages #=> [:english, :french]
102
+ bob.french? #=> throws NoMethodError: undefined method `french?'
103
+ bob.french = false #=> throws NoMethodError: undefined method `french='
104
+ User.french #=> throws NoMethodError: undefined method `french'
105
+
106
+ 5. Easy Rails integration:
107
+
108
+ Given a `User` is declared as:
109
+
110
+ class User < ActiveRecord::Base
111
+ as_set :roles, [:management, :accounting, :human_resources]
112
+ end
113
+
114
+ Adjust strong parameters to allow roles assignment:
115
+
116
+ params.require(:user).permit(:roles => [])
117
+
118
+ And then render a collection of checkboxes:
119
+
120
+ = form_for @user do |f|
121
+ = f.collection_check_boxes(:roles, User.roles, :to_sym, :to_sym) do |b|
122
+ = b.check_box
123
+ = b.label do
124
+ = t("application.roles.#{b.text}")
125
+
126
+ ## Contributing
127
+
128
+ 1. Fork it
129
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
130
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
131
+ 4. Push to the branch (`git push origin my-new-feature`)
132
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,18 @@
1
+ require 'simple_enum/enum_hash'
2
+
3
+ module SimpleSet
4
+ class SetHash < ::SimpleEnum::EnumHash
5
+ def initialize(args = [], strings = false)
6
+ super()
7
+
8
+ if args.is_a?(Hash) then
9
+ args.each { |k,v| set_value_for_reverse_lookup(k, v) }
10
+ else
11
+ ary = args.send(args.respond_to?(:enum_with_index) ? :enum_with_index : :each_with_index).map { |x,y| [ x, 2**y ] } unless args.first.respond_to?(:map)
12
+ ary = args.map { |e| [e, 2**e.id] } if args.first.respond_to?(:map) && !args.first.is_a?(Array)
13
+ ary ||= args
14
+ ary.each { |e| set_value_for_reverse_lookup(e[0], strings ? e[0].to_s : e[1]) }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleSet
2
+ VERSION = "0.0.1"
3
+ end
data/lib/simple_set.rb ADDED
@@ -0,0 +1,141 @@
1
+ require 'active_support'
2
+ require 'active_support/inflector'
3
+
4
+ require 'simple_set/version'
5
+ require 'simple_set/set_hash'
6
+
7
+ require 'active_support/deprecation'
8
+
9
+ module SimpleSet
10
+ class << self
11
+ def default_options
12
+ @default_options ||= {
13
+ whiny: true,
14
+ }
15
+ end
16
+
17
+ def included(base)
18
+ base.send :class_attribute, :simple_set_definitions, instance_writer: false, instance_reader: false
19
+ base.send :extend, ClassMethods
20
+ end
21
+ end
22
+
23
+ module ClassMethods
24
+ # Provides ability to create simple sets based on hashes or arrays, backed
25
+ # by integer columns (but not limited to integer columns).
26
+ #
27
+ # Columns are supposed to be suffixed by <tt>_cd</tt>, if not, use
28
+ # <tt>:column => 'the_column_name'</tt>, so some example migrations:
29
+ #
30
+ # add_column :users, :roles_cd, :integer
31
+ # add_column :users, :permissions, :integer # and a custom column...
32
+ #
33
+ # and then in your model:
34
+ #
35
+ # class User
36
+ # as_set :roles, [:management, :accounting]
37
+ # end
38
+ #
39
+ # # or use a hash:
40
+ #
41
+ # class User
42
+ # as_set :user_permissions, { create_invoice: 1, send_invoice: 2, create_user: 4, all: 7 }, column: 'permissions'
43
+ # end
44
+ #
45
+ # Now it's possible to access the set and the internally stored value like:
46
+ #
47
+ # john_doe = User.new
48
+ # john_doe.roles #=> []
49
+ # john_doe.roles = [:accounting]
50
+ # john_doe.roles #=> [:accounting]
51
+ # john_doe.roles_cd #=> 2
52
+ #
53
+ # And to make life a tad easier: a few shortcut methods to work with the set are also created.
54
+ #
55
+ # john_doe.accounting? #=> true
56
+ # john_doe.accounting = false
57
+ # john_doe.accounting? #=> false
58
+ #
59
+ # === Configuration options:
60
+ # * <tt>:column</tt> - Specifies a custom column name, instead of the
61
+ # default suffixed <tt>_cd</tt> column.
62
+ # * <tt>:prefix</tt> - Define a prefix, which is prefixed to the shortcut
63
+ # methods (e.g. <tt><symbol>=</tt> and <tt><symbol>?</tt>), if it's set
64
+ # to <tt>true</tt> the enumeration name is used as a prefix, else a
65
+ # custom prefix (symbol or string) (default is <tt>nil</tt> => no prefix)
66
+ # * <tt>:slim</tt> - If set to <tt>true</tt> no shortcut methods for all
67
+ # enumeration values are being generated, if set to <tt>:class</tt> only
68
+ # class-level shortcut methods are disabled (default is <tt>nil</tt> =>
69
+ # they are generated)
70
+ # * <tt>:whiny</tt> - Boolean value which if set to <tt>true</tt> will
71
+ # throw an <tt>ArgumentError</tt> if an invalid value is passed to the
72
+ # setter (e.g. a value for which no enumeration exists). if set to
73
+ # <tt>false</tt> no exception is thrown and the internal value is left
74
+ # untouched (default is <tt>true</tt>)
75
+ def as_set(set_cd, values, options = {})
76
+ options = SimpleSet.default_options.merge({column: "#{set_cd}_cd"}).merge(options)
77
+ options.assert_valid_keys(:column, :prefix, :slim, :whiny)
78
+
79
+ metaclass = (class << self; self; end)
80
+
81
+ values = SimpleSet::SetHash.new(values)
82
+
83
+ define_method("#{set_cd}") do
84
+ current = send(options[:column])
85
+ return nil if current.nil?
86
+ values.select { |k,v| v == current & v }.keys
87
+ end
88
+
89
+ define_method("#{set_cd}=") do |new_values|
90
+ real = nil
91
+ if ! new_values.nil? then
92
+ new_values = new_values.reject { |x| x == ''}.collect { |x| x.to_sym }
93
+ real = new_values.collect do |k|
94
+ if values.has_key?(k) then
95
+ values[k]
96
+ else
97
+ raise(ArgumentError, "Invalid set value : #{k}") if options[:whiny]
98
+ 0
99
+ end
100
+ end.inject(:|)
101
+ end
102
+ send("#{options[:column]}=", real)
103
+ end
104
+
105
+ metaclass.send :define_method, "#{set_cd}" do
106
+ return values.keys
107
+ end
108
+
109
+ if options[:slim] != true then
110
+ prefix = options[:prefix] && "#{options[:prefix] == true ? set_cd.to_s.singularize : options[:prefix]}_"
111
+ values.each do |k,code|
112
+ sym = SetHash.symbolize(k)
113
+
114
+ define_method("#{prefix}#{sym}?") do
115
+ current = send(options[:column]) || 0
116
+ code == (code & current)
117
+ end
118
+
119
+ define_method("#{prefix}#{sym}=") do |value|
120
+ current = send(options[:column]) || 0
121
+ if value then
122
+ current |= code
123
+ else
124
+ current &= ~code
125
+ end
126
+ send("#{options[:column]}=", current)
127
+ code == (current & code)
128
+ end
129
+
130
+ unless options[:slim] == :class then
131
+ metaclass.send(:define_method, "#{prefix}#{sym}", Proc.new { |*args| args.first ? k : code })
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ ActiveSupport.on_load(:active_record) do
140
+ ActiveRecord::Base.send(:include, SimpleSet)
141
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'simple_set/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "simple_set"
8
+ spec.version = SimpleSet::VERSION
9
+ spec.authors = ["Romain Tartière"]
10
+ spec.email = ["romain@blogreen.org"]
11
+ spec.summary = %q{Simple set-like field support for ActiveModel}
12
+ spec.homepage = "https://github.com/smortex/simple_set"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "simple_enum", "~> 1.6.8"
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "rspec"
25
+ end
@@ -0,0 +1,280 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleSet do
4
+ it 'should raise on error when manipulating invalid values' do
5
+ named_model('TestExceptions') do
6
+ as_set :values, [:a, :b]
7
+ end
8
+
9
+ sample = TestExceptions.new
10
+ expect { sample.values = [:a] }.to_not raise_error
11
+ expect { sample.values = [:b] }.to_not raise_error
12
+ expect { sample.values = [:c] }.to raise_error(ArgumentError)
13
+ end
14
+
15
+ it 'should accept an array of symbols' do
16
+ named_model('InitWithArrayOfSymbol') do
17
+ as_set :values, [:a, :b, :c, :d, :e, :f]
18
+ end
19
+
20
+ InitWithArrayOfSymbol.a.should == 1
21
+ InitWithArrayOfSymbol.b.should == 2
22
+ InitWithArrayOfSymbol.c.should == 4
23
+ InitWithArrayOfSymbol.d.should == 8
24
+ InitWithArrayOfSymbol.e.should == 16
25
+ InitWithArrayOfSymbol.f.should == 32
26
+ end
27
+
28
+ it 'should accept a hash' do
29
+ named_model('InitWithHash') do
30
+ as_set :values, { a: 1, b: 2, c: 4, d: 8, all: 15 }
31
+ end
32
+
33
+ InitWithHash.a.should == 1
34
+ InitWithHash.b.should == 2
35
+ InitWithHash.c.should == 4
36
+ InitWithHash.d.should == 8
37
+ InitWithHash.all.should == 15
38
+
39
+ sample = InitWithHash.new
40
+ sample.all = true
41
+ sample.a?.should be_true
42
+ sample.b?.should be_true
43
+ sample.c?.should be_true
44
+ sample.d?.should be_true
45
+ sample.all?.should be_true
46
+ sample.b = false
47
+ sample.all?.should be_false
48
+ sample.b = true
49
+ sample.all?.should be_true
50
+ end
51
+
52
+ it 'should distinguish nil from empty set' do
53
+ named_model('NilOrEmpty') do
54
+ as_set :values, [:a, :b]
55
+ end
56
+
57
+ sample = NilOrEmpty.new
58
+
59
+ sample.a?.should be_false
60
+ sample.b?.should be_false
61
+ sample.values_cd.should == nil
62
+ sample.values.should == nil
63
+
64
+ sample.values = [:a]
65
+ sample.values.should == [:a]
66
+ sample.values = nil
67
+ sample.values.should == nil
68
+
69
+ sample.a = true
70
+ sample.values.should == [:a]
71
+ sample.a = false
72
+ sample.values.should == []
73
+
74
+ sample.values = nil
75
+ sample.values.should == nil
76
+ sample.a = false
77
+ sample.values.should == []
78
+ end
79
+
80
+ it 'should support fields with a default value' do
81
+ named_model('FieldWithDefaultValue') do
82
+ as_set :values_with_default, [:x, :y]
83
+ end
84
+
85
+ sample = FieldWithDefaultValue.new
86
+ sample.values_with_default_cd.should == 2
87
+ sample.values_with_default.should == [:y]
88
+
89
+ sample.values_with_default = nil
90
+ sample.values_with_default.should == nil
91
+ end
92
+
93
+ it 'should work outside activerecord' do
94
+ class FruitsEater
95
+ include SimpleSet
96
+ as_set :fruits_i_like, [:apples, :bananas, :pinaple]
97
+ attr_accessor :fruits_i_like_cd
98
+ end
99
+
100
+ sample = FruitsEater.new
101
+ sample.fruits_i_like = [:apples, :pinaple]
102
+ sample.fruits_i_like_cd.should == 5
103
+ end
104
+
105
+ it 'should return acceptable values' do
106
+ named_model('AcceptableValues') do
107
+ as_set :spoken_languages, [:english, :french, :german, :japanese]
108
+ end
109
+
110
+ AcceptableValues.spoken_languages.should == [:english, :french, :german, :japanese]
111
+ end
112
+
113
+ it 'should support Rails assignment' do
114
+ named_model('User') do
115
+ as_set :values, [:foo_manager, :bar_manager, :baz_manager]
116
+ end
117
+
118
+ sample = User.new
119
+ sample.values = ["foo_manager", "baz_manager", ""]
120
+ sample.values.should == [:foo_manager, :baz_manager]
121
+ end
122
+
123
+ # ___ _ _
124
+ # / _ \ _ __ | |_(_) ___ _ __ ___
125
+ # | | | | '_ \| __| |/ _ \| '_ \/ __|
126
+ # | |_| | |_) | |_| | (_) | | | \__ \
127
+ # \___/| .__/ \__|_|\___/|_| |_|___/
128
+ # |_|
129
+
130
+ describe 'options' do
131
+
132
+ # _ _
133
+ # (_)__ ___| |_ _ _ __ _ _
134
+ # _/ _/ _ \ | || | ' \| ' \
135
+ # (_)__\___/_|\_,_|_|_|_|_||_|
136
+ #
137
+
138
+ describe ":column" do
139
+ it 'should support a custom column name' do
140
+ named_model('TestOptionColumn1') do
141
+ as_set :languages, [:english, :french, :german, :japanese], column: 'custom_name'
142
+ end
143
+
144
+ sample = TestOptionColumn1.new
145
+ sample.languages = [:french, :german]
146
+ sample.english?.should be_false
147
+ sample.french?.should be_true
148
+ sample.german?.should be_true
149
+ sample.japanese?.should be_false
150
+ sample.custom_name.should == 6
151
+ end
152
+ end
153
+
154
+ # _ __ _
155
+ # (_)_ __ _ _ ___ / _(_)_ __
156
+ # _| '_ \ '_/ -_) _| \ \ /
157
+ # (_) .__/_| \___|_| |_/_\_\
158
+ # |_|
159
+
160
+ describe ':prefix' do
161
+ it "should support automatic prefix in getters and setters" do
162
+ named_model('TestOptionPrefix1') do
163
+ as_set :spoken_languages, [:english, :french, :german, :japanese], prefix: true
164
+ end
165
+
166
+ sample = TestOptionPrefix1.new
167
+ sample.should respond_to(:spoken_language_english?)
168
+ sample.should respond_to(:spoken_language_french?)
169
+ sample.should respond_to(:spoken_language_german?)
170
+ sample.should respond_to(:spoken_language_japanese?)
171
+
172
+ sample.should respond_to(:spoken_language_english=)
173
+ sample.should respond_to(:spoken_language_french=)
174
+ sample.should respond_to(:spoken_language_german=)
175
+ sample.should respond_to(:spoken_language_japanese=)
176
+
177
+ TestOptionPrefix1.should respond_to(:spoken_language_english)
178
+ TestOptionPrefix1.should respond_to(:spoken_language_french)
179
+ TestOptionPrefix1.should respond_to(:spoken_language_german)
180
+ TestOptionPrefix1.should respond_to(:spoken_language_japanese)
181
+
182
+ sample.should_not respond_to(:japanese?)
183
+ end
184
+
185
+ it "should support custom prefix in getters and setters" do
186
+ named_model('TestOptionPrefix2') do
187
+ as_set :spoken_languages, [:english, :french, :german, :japanese], prefix: 'speaks'
188
+ end
189
+
190
+ sample = TestOptionPrefix2.new
191
+ sample.should respond_to(:speaks_english?)
192
+ sample.should respond_to(:speaks_french?)
193
+ sample.should respond_to(:speaks_german?)
194
+ sample.should respond_to(:speaks_japanese?)
195
+
196
+ sample.should respond_to(:speaks_english=)
197
+ sample.should respond_to(:speaks_french=)
198
+ sample.should respond_to(:speaks_german=)
199
+ sample.should respond_to(:speaks_japanese=)
200
+
201
+ TestOptionPrefix2.should respond_to(:speaks_english)
202
+ TestOptionPrefix2.should respond_to(:speaks_french)
203
+ TestOptionPrefix2.should respond_to(:speaks_german)
204
+ TestOptionPrefix2.should respond_to(:speaks_japanese)
205
+
206
+ sample.should_not respond_to(:japanese?)
207
+ end
208
+ end
209
+
210
+ # _ _ _
211
+ # (_)__| (_)_ __
212
+ # _(_-< | | ' \
213
+ # (_)__/_|_|_|_|_|
214
+ #
215
+
216
+ describe ":slim" do
217
+ it 'should not generate instance nor class members when true is passed' do
218
+ named_model('TestOptionSlim1') do
219
+ as_set :spoken_languages, [:english, :french, :german, :japanese], slim: true
220
+ end
221
+
222
+ TestOptionSlim1.should_not respond_to(:english)
223
+ TestOptionSlim1.should_not respond_to(:french)
224
+ TestOptionSlim1.should_not respond_to(:german)
225
+ TestOptionSlim1.should_not respond_to(:japanese)
226
+
227
+ sample = TestOptionSlim1.new
228
+ sample.should_not respond_to(:english?)
229
+ sample.should_not respond_to(:french?)
230
+ sample.should_not respond_to(:german?)
231
+ sample.should_not respond_to(:japanese?)
232
+
233
+ sample.should_not respond_to(:english=)
234
+ sample.should_not respond_to(:french=)
235
+ sample.should_not respond_to(:german=)
236
+ sample.should_not respond_to(:japanese=)
237
+ end
238
+
239
+ it 'should only generate instance members when :class is passed' do
240
+ named_model('TestOptionSlim2') do
241
+ as_set :spoken_languages, [:english, :french, :german, :japanese], slim: :class
242
+ end
243
+
244
+ TestOptionSlim2.should_not respond_to(:english)
245
+ TestOptionSlim2.should_not respond_to(:french)
246
+ TestOptionSlim2.should_not respond_to(:german)
247
+ TestOptionSlim2.should_not respond_to(:japanese)
248
+
249
+ sample = TestOptionSlim2.new
250
+ sample.should respond_to(:english?)
251
+ sample.should respond_to(:french?)
252
+ sample.should respond_to(:german?)
253
+ sample.should respond_to(:japanese?)
254
+
255
+ sample.should respond_to(:english=)
256
+ sample.should respond_to(:french=)
257
+ sample.should respond_to(:german=)
258
+ sample.should respond_to(:japanese=)
259
+ end
260
+ end
261
+
262
+ # _ _ _
263
+ # (_)_ __ _| |_ (_)_ _ _ _
264
+ # _\ V V / ' \| | ' \ || |
265
+ # (_)\_/\_/|_||_|_|_||_\_, |
266
+ # |__/
267
+
268
+ describe ':whiny' do
269
+ it 'should not raise exception on invalid value' do
270
+ named_model('TestOptionWhiny1') do
271
+ as_set :spoken_languages, [:english, :french, :german, :japanese], whiny: false
272
+ end
273
+
274
+ sample = TestOptionWhiny1.new
275
+ expect { sample.spoken_languages = [:french, :italian, :japanese] }.to_not raise_error
276
+ sample.spoken_languages.should == [:french, :japanese]
277
+ end
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'simple_set'
3
+ require 'support/models'
@@ -0,0 +1,23 @@
1
+ require 'active_record'
2
+
3
+ def named_model(class_name, &block)
4
+ begin
5
+ return class_name.constantize
6
+ rescue NameError
7
+ klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
8
+ klass.module_eval do
9
+ self.table_name = 'dummies'
10
+ instance_eval &block
11
+ end
12
+ klass
13
+ end
14
+ end
15
+
16
+ ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
17
+
18
+ ActiveRecord::Base.connection.create_table :dummies do |t|
19
+ t.integer :values_cd
20
+ t.integer :values_with_default_cd, default: 2
21
+ t.integer :spoken_languages_cd
22
+ t.integer :custom_name
23
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_set
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Romain Tartière
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: simple_enum
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.8
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 1.6.8
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - romain@blogreen.org
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .rspec
78
+ - .travis.yml
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - lib/simple_set.rb
84
+ - lib/simple_set/set_hash.rb
85
+ - lib/simple_set/version.rb
86
+ - simple_set.gemspec
87
+ - spec/simple_set_spec.rb
88
+ - spec/spec_helper.rb
89
+ - spec/support/models.rb
90
+ homepage: https://github.com/smortex/simple_set
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.2.1
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Simple set-like field support for ActiveModel
114
+ test_files:
115
+ - spec/simple_set_spec.rb
116
+ - spec/spec_helper.rb
117
+ - spec/support/models.rb
118
+ has_rdoc: