simple_set 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: