code-box 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,21 +1,21 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- code-box (0.5.0)
4
+ code-box (0.5.1)
5
5
  activerecord (~> 3.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activemodel (3.2.6)
11
- activesupport (= 3.2.6)
10
+ activemodel (3.2.7)
11
+ activesupport (= 3.2.7)
12
12
  builder (~> 3.0.0)
13
- activerecord (3.2.6)
14
- activemodel (= 3.2.6)
15
- activesupport (= 3.2.6)
13
+ activerecord (3.2.7)
14
+ activemodel (= 3.2.7)
15
+ activesupport (= 3.2.7)
16
16
  arel (~> 3.0.2)
17
17
  tzinfo (~> 0.3.29)
18
- activesupport (3.2.6)
18
+ activesupport (3.2.7)
19
19
  i18n (~> 0.6)
20
20
  multi_json (~> 1.0)
21
21
  arel (3.0.2)
data/README.md CHANGED
@@ -1,3 +1,8 @@
1
+ # Notes
2
+
3
+ If you re using ActiveRecord ~> 4.0.0 use the version ~> 0.6
4
+ If you re using ActiveRecord ~> 3.0 use the version ~> 0.5.0
5
+
1
6
  # CodeBox::CodeAttribute
2
7
 
3
8
  Lets you define attributes as codes, instead keys (ids). For simple option storage saving a string code is often more simple an conveniant the storing an artificial id-key referencing a special code object.
@@ -134,12 +139,12 @@ Options are:
134
139
  If `true` the uniqueness validation is scoped by the attribute `type` (default false).
135
140
  * `:uniqueness_case_sensitive => true`
136
141
  If `true` the the uniqueness validation is case sensitive (default true).
137
- * `:position_attr => :position
142
+ * `:position_attr => :position`
138
143
  If present, the order when fetching the codes is done with this expression (default scope - means - if you want to omit the order used `unscoped` on any AR operation).
139
144
 
140
- All options except `:code_attribute` are used only for ActiveRecord models.
145
+ All options except `:code_attribute` are used __only__ for ActiveRecord models.
141
146
 
142
- If `*codes` are provided the following code constants will be defined when calling `acts_as_code('male', 'female', code_attribute: 'code')`
147
+ If `*codes` are provided the following code constants will be defined as shown in the example below.
143
148
 
144
149
  __IMPORTANT__ Code object constants will only be created when the code object is not an ActiveRecord model!
145
150
 
@@ -150,7 +155,7 @@ __IMPORTANT__ Code object constants will only be created when the code object is
150
155
  # acts_as_code('male', 'female') # Code attribute name will be 'code'
151
156
 
152
157
 
153
- # Given codes 'male' an 'female' the following constants will be defined:
158
+ # Given codes 'male' and 'female' the following constants will be defined:
154
159
  #
155
160
  # module Codes
156
161
  # Male = 'male'
@@ -158,7 +163,7 @@ __IMPORTANT__ Code object constants will only be created when the code object is
158
163
  # All = [Male, Female]
159
164
  # end
160
165
  #
161
- # Below constants pnly is is not ActiveRecod model!
166
+ # Below constants are only currently only defined if the hosting class not an ActiveRecod model (as in this sample).
162
167
  # Male = Gender.new('male')
163
168
  # Female = Gender.new('female')
164
169
  # All = [Male, Female]
@@ -166,7 +171,35 @@ __IMPORTANT__ Code object constants will only be created when the code object is
166
171
  end
167
172
 
168
173
 
169
- Furthermote àcts_as_code` defines the following methods:
174
+ If `*codes` are provided - in addition the following test_methods are defined:
175
+
176
+ class Gender
177
+ include CodeBox::ActsAsCode['male', 'female'] # Code attribute name will be 'code'
178
+ # Above is a shortcut for...
179
+ # include CodeBox::ActsAsCode
180
+ # acts_as_code('male', 'female') # Code attribute name will be 'code'
181
+
182
+
183
+ # Given codes 'male' and 'female' the following constants will be defined:
184
+ # ... al the stuff above
185
+ #
186
+ # def male?
187
+ # code == Codes::Male
188
+ # end
189
+ #
190
+ # def female?
191
+ # code == Codes::Female
192
+ # end
193
+ #
194
+ end
195
+
196
+ Pass the option `define_test_methods: false` if you don't want to have test-methods generated.
197
+ If you prefer the all test-methods prefixed with e.g. `is_` so the methods above look like `is_male?` then you can configure this
198
+ globaly by defining `CodeBox.test_method_prefix='is_'`.
199
+
200
+
201
+
202
+ In addition `acts_as_code` defines the following methods:
170
203
 
171
204
  * `.for_code(code)`
172
205
  Answers the code object for the given code (fetched from cache)
@@ -174,18 +207,37 @@ Furthermote àcts_as_code` defines the following methods:
174
207
  * `#translated_code(locale=I18n.locale, *other_locale_options)`
175
208
  Translates the code stored in `code`
176
209
 
177
- * `#translated_code(locale=I18n.locale, *other_locale_options)`
178
- Translates the code stored in `code`
179
-
180
- * `.translate_code(codes_and_options)`
181
- <br/>Translates a single code if `code` is a code, an array of codes of `code` is an array.
210
+ * `.translate_code(codes_and_options)`
211
+ Translates a single code if `code` is a code, an array of codes of `code` is an array.
182
212
  If code is an array the option :build => :zip can be used to build a select option capable array (e.g `[['Switzerland', 'SUI'],['Germany', 'GER'],['Denmark', 'DEN']]`)
183
213
 
184
214
  * `.build_select_options(codes_and_options)`
185
- Build an options array from the passed codes (all codes if no codes are passed). Add an empty option at the beginning if the option `:include_nil` is passed. The localization key is defined in CodeBox (CodeBox.i18n_empty_options_key). If you want the change the default key `shared.options.pls_select` you can do so in an initializer by calling `CodeBox.i18n_empty_options_key='your.key'`.
215
+ Build an options array from the passed codes (all codes if no codes are passed). Add an empty option at the beginning if the option `:include_empty` is passed. If `:include_empty` is…
216
+
217
+ * `true`, then options label is derived from the I18n tranlsation of the key defined in CodeBox.i18n_empty_options_key (default is `shared.options.pls_select` - you can change this default). The value of the option is `nil` by default.
218
+ * `false` then no empty option is defined (default)
219
+ * a String then the string is used as label. The value of the option is `nil` by default.
220
+ * a String starting with `i18n.` the the string is considered as a tranlation key (without the `i18n.` part). Value is nil by default.
221
+ * is a Hash then the value is take from the Hashs value for key `:value` (nil if not present), and the label is taken from the value of key `:label` (default CodeBox.i18n_empty_option_key). If a String is present it is interpreted as a plain label or I18n key as described above.
186
222
 
187
- * `.clear_code_cache`
188
- <br/>Clears the cache so its build up on need from all codes from scratch
223
+ ``Examples
224
+
225
+ .build_select_options(include_empty: true)
226
+
227
+ is same as …
228
+
229
+ .build_select_options(include_empty: {})
230
+
231
+ is same as …
232
+
233
+ .build_select_options(include_empty: {label: nil, value: nil})
234
+
235
+ is same as …
236
+
237
+ .build_select_options(include_empty: {label: '<your default key in CodeBox.i18n_empty_options_key>', value: nil})
238
+
239
+ * `.clear_code_cache`
240
+ Clears the cache so its build up again lazy when needed form all codes.
189
241
 
190
242
  * Passing
191
243
 
@@ -216,29 +268,23 @@ Assuming we have a simple ruby class with default code attribute 'code' we can d
216
268
  # raise "Sublass responsibility. You should implement '.all' returning all codes"
217
269
  # end
218
270
 
219
- # @return [Array] List if all code objects (instances of this)
271
+ # @return [Array] List if all code objects (instances of this) - is implemented when codes are defined.
220
272
  def self.all
221
- # you need to implement this
273
+ raise 'Class responsibility - implement method .all returning all code models.'
222
274
  end
223
275
 
224
276
  end
225
277
 
226
- Configuration options are:
227
-
228
- :type => :poro #(default, other :active_record)
229
- :code_attribute => :code #(default) or any other name as symbol
230
-
231
-
232
278
 
233
279
  #### ActiveRecod code objects (:active_record)
234
280
 
235
281
  Assuming we have an ActiveRecod code class with `code_attribute :code` we can defined such a class like
236
282
 
237
283
  class Codes::MySpecificCode < ActiveRecord::Base
238
- include CodeBox::ActsAsCode[:type => :active_record]
284
+ include CodeBox::ActsAsCode[]
239
285
  # Above is actually a shortcut for:
240
286
  # include CodeBox::ActsAsCode
241
- # acts_as_code(:type => :active_record)
287
+ # acts_as_code
242
288
 
243
289
  # Above include creates the following:
244
290
  #
@@ -249,19 +295,31 @@ Assuming we have an ActiveRecod code class with `code_attribute :code` we can de
249
295
 
250
296
  end
251
297
 
252
- Configuration options are:
253
-
254
- :type => :active_record # other :poro(default)
255
- :code_attribute => :code # (default) or any other name as symbol
256
- :polymorphic => false # (default). If `true` the uniqueness validation is scope by the attribute `type`
257
- :uniqueness_case_sensitive => true # (default). If `false` the the uniqueness validation is case insensitive
258
- :position_attr => :position # If present, the order when fetching the codes is done with this expression (default scope - means - if you want to omit the order used `unscoped` on any AR operation).
259
-
260
298
 
261
299
 
262
300
  ### Examples
263
301
  TO BE DONE…
264
302
 
303
+ ## Changelog
304
+
305
+ ### Version 0.5.1
306
+ * Adding testing methods for codes objects. E.g. Code-Object with code 'my_code' get method `#codeObjectInstance.my_code?` defined.
307
+ * Method `.build_select_options` has been changed so you can pass in more flexible empty option configuration (see Readme).
308
+ * Ugrade of Rails 4 Version pending…
309
+
310
+ ### Version 0.6.0
311
+ * Moving to activerecord 4.0.
312
+
313
+ ### Version 0.5.0
314
+ * Change constant definition. Create code constants in a Codes module so the can be included in other places - an document it.
315
+ * Remove option `:model_type. The option is obsolte and can be derived from the including module.
316
+
317
+ ### Version 0.4.*
318
+ * Define constant whens defining codes.
319
+
320
+ ### Version 0.3.*
321
+ * Need to scan the logs…
322
+
265
323
  ## Contributing
266
324
 
267
325
  1. Fork it!
data/code-box.gemspec CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
  require File.expand_path('../lib/code-box/version', __FILE__)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
- gem.name = "code-box"
6
+ gem.name = 'code-box'
7
7
  gem.version = CodeBox::VERSION
8
8
 
9
9
  gem.authors = ["Martin Schweizer"]
@@ -47,21 +47,23 @@ module CodeBox
47
47
 
48
48
  module ClassMethods
49
49
  DefaultOptions = {
50
- :code_attribute => 'code',
51
- :sti => false,
52
- :uniqueness_case_sensitive => true,
53
- :position_attr => :position,
50
+ code_attribute: 'code',
51
+ sti: false,
52
+ uniqueness_case_sensitive: true,
53
+ position_attr: :position,
54
+ define_test_methods: true,
54
55
  }
55
56
 
56
57
  def acts_as_code(*codes_and_or_options)
57
- options = codes_and_or_options.extract_options!
58
- codes = codes_and_or_options
59
- opts = DefaultOptions.merge(options)
60
- code_attr = opts[:code_attribute].to_s
61
- position_attr = opts[:position_attribute]
62
- case_sensitive = opts[:uniqueness_case_sensitive]
58
+ options = codes_and_or_options.extract_options!
59
+ codes = codes_and_or_options
60
+ opts = DefaultOptions.merge(options)
61
+ code_attr = opts[:code_attribute].to_s
62
+ position_attr = opts[:position_attribute]
63
+ case_sensitive = opts[:uniqueness_case_sensitive]
64
+ define_test_methods = opts[:define_test_methods]
63
65
 
64
- model_type = self.ancestors.include?('ActiveRecord::Base'.constantize) ? :active_record : :poro
66
+ model_type = self.ancestors.include?('ActiveRecord::Base'.constantize) ? :active_record : :poro
65
67
 
66
68
  class_eval <<-RUBY_
67
69
  def translated_#{code_attr}(locale = I18n.locale, *options)
@@ -98,12 +100,32 @@ module CodeBox
98
100
  end
99
101
 
100
102
  def self.build_select_options(*args)
101
- options = args.extract_options!
102
- codes = args.empty? ? #{code_attr.pluralize.camelize}::All : args
103
- include_nil = !!options[:include_nil]
103
+ options = args.extract_options!
104
+ codes = args.empty? ? #{code_attr.pluralize.camelize}::All : args
105
+ include_empty = options[:include_empty] || false
106
+ locale = options.fetch(:locale, I18n.locale)
107
+
108
+ label, value = case include_empty
109
+ when Hash
110
+ [
111
+ include_empty.fetch(:label, "i18n.#{CodeBox.i18n_empty_options_key}"),
112
+ include_empty.fetch(:value, nil)
113
+ ]
114
+ when TrueClass
115
+ [ "i18n.#{CodeBox.i18n_empty_options_key}", nil ]
116
+ when String
117
+ [ include_empty, nil ]
118
+ else # is something falsish
119
+ []
120
+ end
121
+
104
122
 
123
+ # If starts with 'i18n.' it is considered an I18n key, else the label itself
105
124
  options = translate_#{code_attr}(codes, build: :zip)
106
- options.unshift [I18n.t(CodeBox.i18n_empty_options_key), nil] if include_nil
125
+ if include_empty
126
+ label = I18n.t(label[5..-1], locale: locale) if label.starts_with?('i18n.')
127
+ options.unshift [label, value]
128
+ end
107
129
 
108
130
  options
109
131
  end
@@ -142,7 +164,7 @@ module CodeBox
142
164
  validates_presence_of :#{code_attr}
143
165
  validates_uniqueness_of :#{code_attr}#{opts[:sti] ? ', :scope => :type' : ' '}, :case_sensitive => #{case_sensitive}
144
166
 
145
- default_scope order('#{order_expression}')
167
+ default_scope -> { order('#{order_expression}') }
146
168
  CODE
147
169
 
148
170
  when :poro
@@ -156,7 +178,7 @@ module CodeBox
156
178
  end
157
179
 
158
180
  def self.all
159
- raise 'Class responsibility'
181
+ raise 'Class responsibility - implement method .all returning all code models.'
160
182
  end
161
183
 
162
184
  def hash
@@ -175,14 +197,11 @@ module CodeBox
175
197
  raise ArgumentError, "'#{model_type}' is not a valid type. Use :active_record or :poro(default) instead"
176
198
  end
177
199
 
178
- define_codes(*codes)
200
+ define_codes(*codes, define_test_methods) unless codes.empty?
179
201
  end
180
202
 
181
- def define_codes(*codes)
182
- return if codes.empty?
183
-
203
+ def define_codes(*codes, define_test_methods)
184
204
  # --- Define the code constants...
185
-
186
205
  code_attr = self._code_box_code_attr_name
187
206
  model_type = self.ancestors.include?('ActiveRecord::Base'.constantize) ? :active_record : :poro
188
207
 
@@ -204,8 +223,27 @@ module CodeBox
204
223
  codes_module.const_set('All', constants.values.compact)
205
224
  end
206
225
 
226
+
227
+ # Define test methods for each code like e.g.
228
+ # def married?
229
+ # code == Codes::Married
230
+ # end
231
+ if define_test_methods
232
+ method_prefix = CodeBox.test_method_prefix
233
+
234
+ codes.each do |code|
235
+ method_name = "#{method_prefix}#{code.to_s}"
236
+ class_eval <<-CODE
237
+ def #{method_name}?
238
+ #{code_attr} == #{module_name}::#{code.to_s.camelize}
239
+ end
240
+ CODE
241
+ end
242
+ end
243
+
207
244
  return if model_type == :active_record
208
245
 
246
+
209
247
  # --- Define the code instance constants...
210
248
 
211
249
  constants = {}
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module CodeBox
4
- VERSION = "0.5.0"
4
+ VERSION = "0.5.1"
5
5
  end
data/lib/code-box.rb CHANGED
@@ -5,8 +5,9 @@ require 'code-box/acts_as_code'
5
5
 
6
6
  module CodeBox
7
7
  Config = {
8
- :i18n_model_segment => :activerecord,
9
- :i18n_empty_options_key => 'shared.options.pls_select',
8
+ i18n_model_segment: :activerecord,
9
+ i18n_empty_options_key: 'shared.options.pls_select',
10
+ test_method_prefix: '',
10
11
  }
11
12
 
12
13
  def i18n_model_segment=(segment)
@@ -25,5 +26,15 @@ module CodeBox
25
26
  Config[:i18n_empty_options_key]
26
27
  end
27
28
 
28
- module_function :i18n_model_segment, :i18n_model_segment=, :i18n_empty_options_key, :i18n_empty_options_key=
29
+ def test_method_prefix=(prefix)
30
+ Config[:test_method_prefix] = (prefix.nil? ? '' : prefix.strip)
31
+ end
32
+
33
+ def test_method_prefix
34
+ Config[:test_method_prefix]
35
+ end
36
+
37
+ module_function :i18n_model_segment, :i18n_model_segment=,
38
+ :i18n_empty_options_key, :i18n_empty_options_key=,
39
+ :test_method_prefix, :test_method_prefix=
29
40
  end
@@ -57,15 +57,15 @@ class TestActsAsCode < Test::Unit::TestCase
57
57
 
58
58
  def test_code_instance_constant_definitions_w_define_code
59
59
  # Constants
60
- assert Codes::CivilStatusUseDefine.const_defined?('Single')
61
- assert Codes::CivilStatusUseDefine.const_defined?('Married')
62
- assert Codes::CivilStatusUseDefine.const_defined?('All')
60
+ assert Codes::CivilStatus.const_defined?('Single')
61
+ assert Codes::CivilStatus.const_defined?('Married')
62
+ assert Codes::CivilStatus.const_defined?('All')
63
63
 
64
64
  # Constants-Values
65
- assert_equal [Codes::CivilStatusUseDefine::Single, Codes::CivilStatusUseDefine::Married], Codes::CivilStatusUseDefine::All
66
- assert_equal [Codes::CivilStatusUseDefine::Single, Codes::CivilStatusUseDefine::Married], Codes::CivilStatusUseDefine.all
67
- assert_equal Codes::CivilStatusUseDefine::Single.code, 'single'
68
- assert_equal Codes::CivilStatusUseDefine::Married.code, 'married'
65
+ assert_equal [Codes::CivilStatus::Single, Codes::CivilStatus::Married], Codes::CivilStatus::All
66
+ assert_equal [Codes::CivilStatus::Single, Codes::CivilStatus::Married], Codes::CivilStatus.all
67
+ assert_equal Codes::CivilStatus::Single.code, 'single'
68
+ assert_equal Codes::CivilStatus::Married.code, 'married'
69
69
  end
70
70
 
71
71
  def test_code_translation
@@ -79,9 +79,29 @@ class TestActsAsCode < Test::Unit::TestCase
79
79
  options_array = Codes::CivilStatus.build_select_options
80
80
  assert_equal options_array.size, 2
81
81
 
82
- options_array = Codes::CivilStatus.build_select_options(include_nil: true)
82
+ options_array = Codes::CivilStatus.build_select_options(include_empty: true)
83
+ assert_equal options_array.size, 3
84
+ assert_equal options_array.first[1], nil
85
+ end
86
+
87
+ def test_options_building_with_text_label
88
+ options_array = Codes::CivilStatus.build_select_options(include_empty: { label: 'MyLabel' })
89
+ assert_equal options_array.size, 3
90
+ assert_equal options_array.first[0], 'MyLabel'
91
+ assert_equal options_array.first[1], nil
92
+ end
93
+
94
+ def test_options_building_with_custom_value
95
+ options_array = Codes::CivilStatus.build_select_options(include_empty: { value: 'all' })
96
+ assert_equal options_array.size, 3
97
+ assert_equal options_array.first[1], 'all'
98
+ end
99
+
100
+ def test_options_building_with_custom_label_and_value
101
+ options_array = Codes::CivilStatus.build_select_options(include_empty: { label: 'Yaiii', value: 'all' })
83
102
  assert_equal options_array.size, 3
84
- puts options_array: options_array
103
+ assert_equal options_array.first[0], 'Yaiii'
104
+ assert_equal options_array.first[1], 'all'
85
105
  end
86
106
 
87
107
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code-box
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-10 00:00:00.000000000 Z
12
+ date: 2013-09-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord