code-box 0.3.1 → 0.4.0
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.
- data/README.md +31 -19
- data/lib/code-box/acts_as_code.rb +103 -8
- data/lib/code-box/version.rb +1 -1
- data/test/code-box/test_acts_as_code.rb +33 -7
- data/test/resources/models.rb +4 -11
- metadata +3 -8
data/README.md
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
# CodeBox::CodeAttribute
|
2
2
|
|
3
3
|
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.
|
4
|
-
|
4
|
+
|
5
|
+
CodeBox:
|
6
|
+
|
7
|
+
* lets you define code attributes
|
8
|
+
* provides translation of this codes __or__
|
9
|
+
* provides access to associated code objects (see below) in various ways
|
10
|
+
* __and__ furthermore enables an easy way to define code objects
|
5
11
|
|
6
12
|
|
7
13
|
|
@@ -67,7 +73,7 @@ Example
|
|
67
73
|
code_attribute :nationality, :lookup_type => :lookup
|
68
74
|
end
|
69
75
|
|
70
|
-
# Note: Below class is a plain sample implementation. Code objects can be built easier with
|
76
|
+
# Note: Below class is a plain sample implementation. Code objects can be built easier with
|
71
77
|
# 'ActsAsCode' include (see below)
|
72
78
|
class Code::Nationality
|
73
79
|
attr_accessor :code, :name
|
@@ -120,44 +126,47 @@ As describe above code_attributes can reference code objects if the `code_attrib
|
|
120
126
|
|
121
127
|
Making an code object `acts_as_code` provides the following features:
|
122
128
|
|
123
|
-
*
|
124
|
-
Translates the code stored in `code`
|
129
|
+
* `#translated_code(locale=I18n.locale, *other_locale_options)`
|
130
|
+
<br/>Translates the code stored in `code`
|
125
131
|
|
126
|
-
*
|
127
|
-
Translates the code stored in `code`
|
132
|
+
* `#translated_code(locale=I18n.locale, *other_locale_options)`
|
133
|
+
<br/>Translates the code stored in `code`
|
128
134
|
|
129
135
|
* `.translate_code(code, *options)`
|
130
|
-
Translates a single code if `code` is a code, an array of codes of `code` is an array.
|
136
|
+
<br/>Translates a single code if `code` is a code, an array of codes of `code` is an array.
|
131
137
|
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']]`)
|
132
138
|
|
133
|
-
* `.for_code(code)
|
134
|
-
Answers the code object for the given code (fetched from cache)
|
139
|
+
* `.for_code(code)`:
|
140
|
+
<br/>Answers the code object for the given code (fetched from cache)
|
135
141
|
|
136
142
|
* `.clear_code_cache`
|
137
|
-
Clears the cache so its build up on need from all codes from scratch
|
143
|
+
<br/>Clears the cache so its build up on need from all codes from scratch
|
138
144
|
|
139
145
|
|
140
146
|
__Note:__ The code name can be configures using the `:code_attribute` option.
|
141
|
-
`:code_attribute => :iso_code` leads to methods like
|
147
|
+
`:code_attribute => :iso_code` leads to methods like `#translate_iso_code` etc.
|
142
148
|
|
143
149
|
|
144
150
|
#### Plain old ruby object codes (:poro)
|
145
151
|
|
146
|
-
Assuming we have a simple ruby class with default code attribute 'code' we can defined such a class like
|
152
|
+
Assuming we have a simple ruby class with default code attribute 'code' we can defined such a class like:
|
147
153
|
|
148
154
|
class Codes::MySpecificCode
|
149
|
-
include CodeBox::ActsAsCode
|
155
|
+
include CodeBox::ActsAsCode[]
|
156
|
+
# Above is actually a shortcut for:
|
157
|
+
# include CodeBox::ActsAsCode
|
158
|
+
# acts_as_code
|
150
159
|
|
151
|
-
# Above include
|
160
|
+
# Above include creates the following:
|
152
161
|
#
|
153
162
|
# attr_accessor :code
|
154
163
|
#
|
155
|
-
# def initialize(code)
|
156
|
-
# @code = code
|
164
|
+
# def initialize(code)
|
165
|
+
# @code = code
|
157
166
|
# end
|
158
|
-
#
|
167
|
+
#
|
159
168
|
# def self.all
|
160
|
-
# raise "Sublass responsibility. You should implement '.all' returning all codes"
|
169
|
+
# raise "Sublass responsibility. You should implement '.all' returning all codes"
|
161
170
|
# end
|
162
171
|
|
163
172
|
# @return [Array] List if all code objects (instances of this)
|
@@ -180,8 +189,11 @@ Assuming we have an ActiveRecod code class with `code_attribute :code` we can de
|
|
180
189
|
|
181
190
|
class Codes::MySpecificCode < ActiveRecord::Base
|
182
191
|
include CodeBox::ActsAsCode[:type => :active_record]
|
192
|
+
# Above is actually a shortcut for:
|
193
|
+
# include CodeBox::ActsAsCode
|
194
|
+
# acts_as_code(:type => :active_record)
|
183
195
|
|
184
|
-
# Above include
|
196
|
+
# Above include creates the following:
|
185
197
|
#
|
186
198
|
# validates_presence_of :code
|
187
199
|
# validates_uniqueness_of :code
|
@@ -48,7 +48,7 @@ module CodeBox
|
|
48
48
|
module ClassMethods
|
49
49
|
DefaultOptions = {
|
50
50
|
:type => :poro,
|
51
|
-
:code_attribute =>
|
51
|
+
:code_attribute => 'code',
|
52
52
|
:polymorphic => false,
|
53
53
|
:uniqueness_case_sensitive => true,
|
54
54
|
:position_attr => :position,
|
@@ -58,14 +58,28 @@ module CodeBox
|
|
58
58
|
options = codes_and_or_options.extract_options!
|
59
59
|
codes = codes_and_or_options
|
60
60
|
opts = DefaultOptions.merge(options)
|
61
|
-
code_attr = opts[:code_attribute]
|
61
|
+
code_attr = opts[:code_attribute].to_s
|
62
62
|
position_attr = opts[:position_attribute]
|
63
63
|
case_sensitive = opts[:uniqueness_case_sensitive]
|
64
64
|
model_type = opts.delete(:type)
|
65
65
|
|
66
66
|
# Create a constant for each code
|
67
|
-
codes.
|
68
|
-
|
67
|
+
if !codes.empty?
|
68
|
+
code_constants = {}
|
69
|
+
codes.each do |code|
|
70
|
+
constant_name = "#{(code_attr+'_'+code.to_s).to_s.camelize}"
|
71
|
+
constant = const_set(constant_name, code.to_s) unless const_defined?(constant_name)
|
72
|
+
code_constants[constant_name] = constant
|
73
|
+
end
|
74
|
+
raise "Could not define all code constants. Only defined for #{code_constants.values.compact.inspect}" unless code_constants.values.compact.size == codes.size
|
75
|
+
|
76
|
+
pl_code_attr = code_attr.pluralize.camelize
|
77
|
+
constant_name = "All#{pl_code_attr}"
|
78
|
+
if const_defined?(constant_name)
|
79
|
+
raise "Could not define constant '#{const_name}' for all codes."
|
80
|
+
else
|
81
|
+
const_set(constant_name, code_constants.values.compact)
|
82
|
+
end
|
69
83
|
end
|
70
84
|
|
71
85
|
class_eval <<-RUBY_
|
@@ -103,11 +117,18 @@ module CodeBox
|
|
103
117
|
def self.initialize_cache
|
104
118
|
Hash[all.map{ |code| [code.#{code_attr}, code] }]
|
105
119
|
end
|
106
|
-
|
107
120
|
RUBY_
|
108
121
|
|
109
122
|
instance_eval <<-CODE
|
110
123
|
class << self
|
124
|
+
def code_box_model_type
|
125
|
+
'#{model_type.to_sym}'
|
126
|
+
end
|
127
|
+
|
128
|
+
def code_box_code_attr_name
|
129
|
+
'#{code_attr}'
|
130
|
+
end
|
131
|
+
|
111
132
|
def code_cache
|
112
133
|
@code_cache ||= initialize_cache
|
113
134
|
end
|
@@ -155,17 +176,91 @@ module CodeBox
|
|
155
176
|
def ==(other)
|
156
177
|
self.equal? other
|
157
178
|
end
|
179
|
+
CODE
|
158
180
|
|
159
|
-
|
160
|
-
|
181
|
+
if codes.empty?
|
182
|
+
class_eval <<-CODE
|
183
|
+
def self.all
|
184
|
+
raise 'Class responsibility'
|
185
|
+
end
|
186
|
+
CODE
|
187
|
+
else
|
188
|
+
code_constants = {}
|
189
|
+
codes.each do |code|
|
190
|
+
constant_name = "#{code.to_s.camelize}"
|
191
|
+
constant = const_set(constant_name, self.new(code.to_s)) unless const_defined?(constant_name)
|
192
|
+
code_constants[constant_name] = constant
|
161
193
|
end
|
162
|
-
|
194
|
+
raise "Could not define all code instance constants. Only defined for #{code_constants.values.compact.inspect}" unless code_constants.values.compact.size == codes.size
|
195
|
+
|
196
|
+
pl_code_attr = code_attr.pluralize.camelize
|
197
|
+
constant_name = 'All'
|
198
|
+
if const_defined?(constant_name)
|
199
|
+
raise "Could not define constant '#{const_name}' for all codes."
|
200
|
+
else
|
201
|
+
const_set(constant_name, code_constants.values.compact)
|
202
|
+
end
|
203
|
+
|
204
|
+
class_eval <<-CODE
|
205
|
+
def self.all
|
206
|
+
All
|
207
|
+
end
|
208
|
+
CODE
|
209
|
+
end
|
163
210
|
|
164
211
|
else
|
165
212
|
raise ArgumentError, "'#{model_type}' is not a valid type. Use :active_record or :poro(default) instead"
|
166
213
|
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def define_codes(*codes)
|
217
|
+
code_attr = self.code_box_code_attr_name
|
218
|
+
model_type = self.code_box_model_type
|
219
|
+
|
220
|
+
return if codes.empty?
|
221
|
+
|
222
|
+
# Create a constant for each code
|
223
|
+
code_constants = {}
|
224
|
+
codes.each do |code|
|
225
|
+
constant_name = "#{(code_attr+'_'+code.to_s).to_s.camelize}"
|
226
|
+
constant = const_set(constant_name, code.to_s) unless const_defined?(constant_name)
|
227
|
+
code_constants[constant_name] = constant
|
228
|
+
end
|
229
|
+
raise "Could not define all code constants. Only defined for #{code_constants.values.compact.inspect}" unless code_constants.values.compact.size == codes.size
|
230
|
+
|
231
|
+
pl_code_attr = code_attr.pluralize.camelize
|
232
|
+
constant_name = "All#{pl_code_attr}"
|
233
|
+
if const_defined?(constant_name)
|
234
|
+
raise "Could not define constant '#{const_name}' for all codes."
|
235
|
+
else
|
236
|
+
const_set(constant_name, code_constants.values.compact)
|
237
|
+
end
|
238
|
+
|
239
|
+
return if self.code_box_model_type == :active_record
|
240
|
+
|
241
|
+
code_constants = {}
|
242
|
+
codes.each do |code|
|
243
|
+
constant_name = "#{code.to_s.camelize}"
|
244
|
+
constant = const_set(constant_name, self.new(code.to_s)) unless const_defined?(constant_name)
|
245
|
+
code_constants[constant_name] = constant
|
246
|
+
end
|
247
|
+
raise "Could not define all code instance constants. Only defined for #{code_constants.values.compact.inspect}" unless code_constants.values.compact.size == codes.size
|
248
|
+
|
249
|
+
pl_code_attr = code_attr.pluralize.camelize
|
250
|
+
constant_name = 'All'
|
251
|
+
if const_defined?(constant_name)
|
252
|
+
raise "Could not define constant '#{const_name}' for all codes."
|
253
|
+
else
|
254
|
+
const_set(constant_name, code_constants.values.compact)
|
255
|
+
end
|
167
256
|
|
257
|
+
class_eval <<-CODE
|
258
|
+
def self.all
|
259
|
+
All
|
260
|
+
end
|
261
|
+
CODE
|
168
262
|
end
|
263
|
+
|
169
264
|
end
|
170
265
|
end
|
171
266
|
end
|
data/lib/code-box/version.rb
CHANGED
@@ -4,12 +4,8 @@ require 'helper'
|
|
4
4
|
|
5
5
|
class TestActsAsCode < Test::Unit::TestCase
|
6
6
|
|
7
|
-
def
|
8
|
-
assert_equal
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_constants
|
12
|
-
assert_equal 2, Codes::CivilStatus::all.size
|
7
|
+
def test_all_methods
|
8
|
+
assert_equal 2, Codes::CivilStatus.all.size
|
13
9
|
|
14
10
|
assert_equal Codes::CivilStatus.for_code('single'), Codes::CivilStatus::all.first
|
15
11
|
assert_equal Codes::CivilStatus.for_code('married'), Codes::CivilStatus::all.last
|
@@ -32,14 +28,44 @@ class TestActsAsCode < Test::Unit::TestCase
|
|
32
28
|
assert_equal code_2, Codes::ArCode.for_code('code_2')
|
33
29
|
end
|
34
30
|
|
35
|
-
def
|
31
|
+
def test_code_constant_definitiones
|
32
|
+
# Constants
|
36
33
|
assert Codes::CivilStatus.const_defined?('CodeSingle')
|
37
34
|
assert Codes::CivilStatus.const_defined?('CodeMarried')
|
35
|
+
assert Codes::CivilStatus.const_defined?('AllCodes')
|
38
36
|
|
37
|
+
# Constants-Values
|
38
|
+
assert_equal [Codes::CivilStatus::CodeSingle, Codes::CivilStatus::CodeMarried], Codes::CivilStatus::AllCodes
|
39
39
|
assert_equal Codes::CivilStatus::CodeMarried, 'married'
|
40
40
|
assert_equal Codes::CivilStatus::CodeSingle, 'single'
|
41
41
|
end
|
42
42
|
|
43
|
+
def test_code_instance_constant_definitions
|
44
|
+
# Constants
|
45
|
+
assert Codes::CivilStatus.const_defined?('Single')
|
46
|
+
assert Codes::CivilStatus.const_defined?('Married')
|
47
|
+
assert Codes::CivilStatus.const_defined?('All')
|
48
|
+
|
49
|
+
# Constants-Values
|
50
|
+
assert_equal [Codes::CivilStatus::Single, Codes::CivilStatus::Married], Codes::CivilStatus::All
|
51
|
+
assert_equal [Codes::CivilStatus::Single, Codes::CivilStatus::Married], Codes::CivilStatus.all
|
52
|
+
assert_equal Codes::CivilStatus::Single.code, 'single'
|
53
|
+
assert_equal Codes::CivilStatus::Married.code, 'married'
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_code_instance_constant_definitions_w_define_code
|
57
|
+
# Constants
|
58
|
+
assert Codes::CivilStatusUseDefine.const_defined?('Single')
|
59
|
+
assert Codes::CivilStatusUseDefine.const_defined?('Married')
|
60
|
+
assert Codes::CivilStatusUseDefine.const_defined?('All')
|
61
|
+
|
62
|
+
# Constants-Values
|
63
|
+
assert_equal [Codes::CivilStatusUseDefine::Single, Codes::CivilStatusUseDefine::Married], Codes::CivilStatusUseDefine::All
|
64
|
+
assert_equal [Codes::CivilStatusUseDefine::Single, Codes::CivilStatusUseDefine::Married], Codes::CivilStatusUseDefine.all
|
65
|
+
assert_equal Codes::CivilStatusUseDefine::Single.code, 'single'
|
66
|
+
assert_equal Codes::CivilStatusUseDefine::Married.code, 'married'
|
67
|
+
end
|
68
|
+
|
43
69
|
def test_code_translation
|
44
70
|
code = Codes::CivilStatus.new('married')
|
45
71
|
|
data/test/resources/models.rb
CHANGED
@@ -21,19 +21,12 @@ module Codes
|
|
21
21
|
|
22
22
|
class CivilStatus
|
23
23
|
include CodeBox::ActsAsCode['single', 'married', :type => :poro]
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
+
class CivilStatusUseDefine
|
27
|
+
include CodeBox::ActsAsCode[:type => :poro]
|
26
28
|
|
27
|
-
|
28
|
-
@code = code
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.all
|
32
|
-
[
|
33
|
-
Codes::CivilStatus.new('single'),
|
34
|
-
Codes::CivilStatus.new('married'),
|
35
|
-
]
|
36
|
-
end
|
29
|
+
define_codes(:single, :married)
|
37
30
|
end
|
38
31
|
|
39
32
|
class AgerType
|
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.
|
4
|
+
version: 0.4.0
|
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:
|
12
|
+
date: 2013-09-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -117,18 +117,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
117
117
|
- - ! '>='
|
118
118
|
- !ruby/object:Gem::Version
|
119
119
|
version: '0'
|
120
|
-
segments:
|
121
|
-
- 0
|
122
|
-
hash: -268048192927979465
|
123
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
121
|
none: false
|
125
122
|
requirements:
|
126
123
|
- - ! '>='
|
127
124
|
- !ruby/object:Gem::Version
|
128
125
|
version: '0'
|
129
|
-
segments:
|
130
|
-
- 0
|
131
|
-
hash: -268048192927979465
|
132
126
|
requirements: []
|
133
127
|
rubyforge_project:
|
134
128
|
rubygems_version: 1.8.21
|
@@ -144,3 +138,4 @@ test_files:
|
|
144
138
|
- test/resources/locale/en.yml
|
145
139
|
- test/resources/models.rb
|
146
140
|
- test/resources/schema.rb
|
141
|
+
has_rdoc:
|