rebase_attr 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1c989126e78f373d7608f11824429b65974311bc
4
- data.tar.gz: 2859dd7b67c93645a72d0ad8f38ee128b9d72d29
3
+ metadata.gz: ea935085ce8abb358a0cf745bed76b3eafcd2d23
4
+ data.tar.gz: 70e69e3bb784845327ff3fa78223bcb9c7c3d0c1
5
5
  SHA512:
6
- metadata.gz: e812eced8377afca51ce32ee032411782b1aba3395df1b7480603011a2c6a3e988406d0d12eb6d3fad162afdab3c0353ab7c67e5256e1add033e540b8991afc3
7
- data.tar.gz: bc4df6f016698c5a4ec2c89c48eda5f243beb5c709a29f10d65331b80f344076c5e4bd7b523adf335bc44b40b39cb8a40a6d8834524a2adba2a4a537cbf383b4
6
+ metadata.gz: 8742d2a06433dfb567b4464d6025bff600502d1eafe487040e9ddb9faf4734d952a35b9bf10d926aaf0278bcd043542fb85c7086e7d3428a6fbd1012ad279639
7
+ data.tar.gz: 2805a5159796f79fea91660ae8886a0bd5378bd7123cd4585f946be19ef21f599f7e4044c1979b549a88ccfcbf03ac48c4d1da7ae80781e28c85a0c11485e660
data/README.md CHANGED
@@ -36,7 +36,7 @@ Example for an active record table with long IDs:
36
36
  #
37
37
 
38
38
  class Bill < ActiveRecord::Base
39
- rebase_attr :id, base: 32, readable: true # only digits and leters, without '0', '1', 'i' and 'l'
39
+ rebase_attr :id, to: 32, readable: true # digits and leters, without '0', 'o', '1' and 'l'
40
40
  end
41
41
  ```
42
42
 
@@ -1,4 +1,5 @@
1
1
  require "rebase_attr/version"
2
+ require "generate_method"
2
3
 
3
4
  module RebaseAttr
4
5
  READABLE_MAPPING = { '0' => 'x', '1' => 'y', 'l' => 'w', 'o' => 'z' }
@@ -9,66 +10,67 @@ module RebaseAttr
9
10
  raise ArgumentError, "#rebase_attr does not accept a block, did you mean to use :convert?" if block_given?
10
11
  raise ArgumentError, "#rebase_attr does not allow :readable option with bases higher than 32, #{to} given" if readable and to > 32
11
12
 
12
- attributes.each do |attr|
13
- # encoders & decoders
14
- define_singleton_method :"encode_#{attr}" do |decoded|
15
- break nil if decoded.nil?
13
+ generate_singleton_methods do
14
+ attributes.each do |attr|
15
+ # encoders & decoders
16
+ define_method :"encode_#{attr}" do |decoded|
17
+ break nil if decoded.nil?
16
18
 
17
- result = decoded
18
- raise TypeError, "decoded value must implement #to_i, #{result.inspect} given" unless result.respond_to?(:to_i)
19
- result = result.to_i(from || 10) if result.is_a?(String)
20
- result = result.to_s(to)
21
- READABLE_MAPPING.each { |s, d| result.gsub!(/#{s}/i, d) } if readable # gsub! to conserve memory
22
- result = convert.respond_to?(:call) ? convert.call(result) : result.public_send(convert) if convert
23
- result
24
- end
25
- define_method :"encode_#{attr}" do |decoded|
26
- self.class.send(:"encode_#{attr}", decoded)
27
- end
19
+ result = decoded
20
+ raise TypeError, "decoded value must implement #to_i, #{result.inspect} given" unless result.respond_to?(:to_i)
21
+ result = result.to_i(from || 10) if result.is_a?(String)
22
+ result = result.to_s(to)
23
+ READABLE_MAPPING.each { |s, d| result.gsub!(/#{s}/i, d) } if readable # gsub! to conserve memory
24
+ result = convert.respond_to?(:call) ? convert.call(result) : result.public_send(convert) if convert
25
+ result
26
+ end
28
27
 
29
- define_singleton_method :"decode_#{attr}" do |encoded|
30
- break nil if encoded.nil?
28
+ define_method :"decode_#{attr}" do |encoded|
29
+ break nil if encoded.nil?
31
30
 
32
- result = encoded
33
- if deconvert
34
- begin
35
- result = result.clone # deconvert to not modify outside variable
36
- rescue TypeError # can't clone, immutable
31
+ result = encoded
32
+ if deconvert
33
+ begin
34
+ result = result.clone # deconvert to not modify outside variable
35
+ rescue TypeError # can't clone, immutable
36
+ end
37
+ result = deconvert.respond_to?(:call) ? deconvert.call(result) : result.public_send(deconvert)
37
38
  end
38
- result = deconvert.respond_to?(:call) ? deconvert.call(result) : result.public_send(deconvert)
39
- end
40
- raise TypeError, "encoded value must implement #to_i, #{result.inspect} given" unless result.respond_to?(:to_i)
41
- if readable
42
- begin
43
- result = result.clone # not modifying outside variable
44
- rescue TypeError # can't clone, immutable
39
+ raise TypeError, "encoded value must implement #to_i, #{result.inspect} given" unless result.respond_to?(:to_i)
40
+ if readable
41
+ begin
42
+ result = result.clone # not modifying outside variable
43
+ rescue TypeError # can't clone, immutable
44
+ end
45
+ READABLE_MAPPING.each { |s, d| result.gsub!(/#{d}/i, s) } # gsub! to conserve memory
45
46
  end
46
- READABLE_MAPPING.each { |s, d| result.gsub!(/#{d}/i, s) } # gsub! to conserve memory
47
+ result = result.to_i(to)
48
+ result = result.to_s(from) if from
49
+ result
47
50
  end
48
- result = result.to_i(to)
49
- result = result.to_s(from) if from
50
- result
51
- end
52
- define_method :"decode_#{attr}" do |encoded|
53
- self.class.send(:"decode_#{attr}", encoded)
54
51
  end
52
+ end
55
53
 
56
- # readers & writers
57
- begin
58
- alias_method :"#{attr}_without_rebase", attr
59
- rescue NameError # reader does not exist
60
- else
61
- define_method attr do
62
- send(:"encode_#{attr}", send(:"#{attr}_without_rebase"))
54
+ generate_methods do
55
+ attributes.each do |attr|
56
+ # encoders & decoders
57
+ define_method :"encode_#{attr}" do |decoded|
58
+ self.class.send(:"encode_#{attr}", decoded)
59
+ end
60
+ define_method :"decode_#{attr}" do |encoded|
61
+ self.class.send(:"decode_#{attr}", encoded)
63
62
  end
64
63
  end
64
+ end
65
65
 
66
- begin
67
- alias_method :"#{attr}_without_rebase=", :"#{attr}="
68
- rescue NameError # writer does not exist
69
- else
66
+ generate_methods(overrider: :rebase) do
67
+ attributes.each do |attr|
68
+ # readers & writers
69
+ define_method attr do
70
+ send(:"encode_#{attr}", respond_to?(:"#{attr}_without_rebase") ? send(:"#{attr}_without_rebase") : super())
71
+ end
70
72
  define_method :"#{attr}=" do |encoded|
71
- send(:"#{attr}_without_rebase=", send(:"decode_#{attr}", encoded))
73
+ respond_to?(:"#{attr}_without_rebase=") ? send(:"#{attr}_without_rebase=", send(:"decode_#{attr}", encoded)) : super(send(:"decode_#{attr}", encoded))
72
74
  end
73
75
  end
74
76
  end
@@ -1,3 +1,3 @@
1
1
  module RebaseAttr
2
- VERSION = "1.1.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_runtime_dependency "generate_method", "~> 1.0"
22
+
21
23
  spec.add_development_dependency "bundler", "~> 1.7"
22
24
  spec.add_development_dependency "rspec", "~> 3.1"
23
25
  spec.add_development_dependency "rspec-its", "~> 1.0"
@@ -1,17 +1,49 @@
1
1
  require 'rebase_attr'
2
2
 
3
- class RebaseTestBase
3
+ class RebaseWithAccessorTestBase
4
4
  attr_accessor :x
5
5
  end
6
6
 
7
+ class RebaseWithoutAccessorTestBase
8
+ def method_missing(method, *args, &block)
9
+ case method
10
+ when :x
11
+ @x
12
+ when :x=
13
+ @x = args.first
14
+ else
15
+ super
16
+ end
17
+ end
18
+ end
19
+
7
20
  # This converts options to local varaibels so they can be used inside the Class.new { }
8
21
  def rebase_class(**options, &block)
9
- Class.new(RebaseTestBase) { rebase_attr(:x, **options, &block) }
22
+ Class.new(RebaseWithAccessorTestBase) { rebase_attr(:x, **options, &block) }
23
+ end
24
+
25
+ def rebase_classes(options_proc, &block)
26
+ context "with accessor" do
27
+ let(:klass) do
28
+ options = instance_eval(&options_proc) # converting to local variable before going inside the Class
29
+ Class.new(RebaseWithAccessorTestBase) { rebase_attr(:x, **options) }
30
+ end
31
+ @with_accessors = true
32
+ instance_eval(&block)
33
+ end
34
+ context "without accessor" do
35
+ let(:klass) do
36
+ options = instance_eval(&options_proc) # converting to local variable before going inside the Class
37
+ Class.new(RebaseWithoutAccessorTestBase) { rebase_attr(:x, **options) }
38
+ end
39
+ @with_accessors = false
40
+ instance_eval(&block)
41
+ end
10
42
  end
11
43
 
12
44
  describe RebaseAttr::Generator do
13
45
  #requires: decoded, encoded
14
- shared_examples_for "values" do
46
+ shared_examples_for "values" do |with_accessors|
15
47
  subject(:instance) { klass.new }
16
48
 
17
49
  describe "#encode" do
@@ -41,13 +73,13 @@ describe RebaseAttr::Generator do
41
73
 
42
74
  describe "#without_rebase" do
43
75
  context "when not nil" do
44
- before { d = decoded; instance.instance_eval { @x = d } } # converting decoded to local variable so I can use it inside instance_eval
45
- its(:x_without_rebase) { should == decoded }
76
+ before { d = decoded; instance.instance_eval { @x = d } if with_accessors } # converting decoded to local variable so I can use it inside instance_eval
77
+ specify { expect(instance.x_without_rebase).to eq(decoded) if with_accessors }
46
78
  end
47
79
 
48
80
  context "when nil" do
49
- before { instance.instance_eval { @x = nil } } # converting decoded to local variable so I can use it inside instance_eval
50
- its(:x_without_rebase) { should be_nil }
81
+ before { instance.instance_eval { @x = nil } if with_accessors } # converting decoded to local variable so I can use it inside instance_eval
82
+ specify { expect(instance.x_without_rebase).to be_nil if with_accessors }
51
83
  end
52
84
  end
53
85
 
@@ -65,13 +97,13 @@ describe RebaseAttr::Generator do
65
97
 
66
98
  describe "#without_rebase=" do
67
99
  context "when not nil" do
68
- before { instance.x_without_rebase = decoded }
69
- specify { expect(instance.instance_eval { @x }).to eq(decoded) }
100
+ before { instance.x_without_rebase = decoded if with_accessors }
101
+ specify { expect(instance.instance_eval { @x }).to eq(decoded) if with_accessors }
70
102
  end
71
103
 
72
104
  context "when nil" do
73
- before { instance.x_without_rebase = nil }
74
- specify { expect(instance.instance_eval { @x }).to be_nil }
105
+ before { instance.x_without_rebase = nil if with_accessors }
106
+ specify { expect(instance.instance_eval { @x }).to be_nil if with_accessors }
75
107
  end
76
108
  end
77
109
  end
@@ -81,42 +113,47 @@ describe RebaseAttr::Generator do
81
113
  shared_context "all except readable" do
82
114
  context "without from" do
83
115
  context "not converted" do
84
- let(:klass) { rebase_class to: to }
85
- let(:decoded) { decoded_default }
86
- let(:encoded) { encoded_default }
87
- it_behaves_like "values"
116
+ rebase_classes proc { { to: to } } do
117
+ let(:decoded) { decoded_default }
118
+ let(:encoded) { encoded_default }
119
+ it_behaves_like "values", @with_accessors
120
+ end
88
121
  end
89
122
 
90
123
  context "converted" do
91
124
  context "named" do
92
- let(:klass) { rebase_class to: to, convert: convert_name, deconvert: deconvert }
93
- let(:decoded) { decoded_default }
94
- let(:encoded) { encoded_convert }
95
- it_behaves_like "values"
125
+ rebase_classes proc { { to: to, convert: convert_name, deconvert: deconvert } } do
126
+ let(:decoded) { decoded_default }
127
+ let(:encoded) { encoded_convert }
128
+ it_behaves_like "values", @with_accessors
129
+ end
96
130
  end
97
131
 
98
132
  context "block" do
99
- let(:klass) { rebase_class to: to, convert: convert_block, deconvert: deconvert }
100
- let(:decoded) { decoded_default }
101
- let(:encoded) { encoded_convert }
102
- it_behaves_like "values"
133
+ rebase_classes proc { { to: to, convert: convert_block, deconvert: deconvert } } do
134
+ let(:decoded) { decoded_default }
135
+ let(:encoded) { encoded_convert }
136
+ it_behaves_like "values", @with_accessors
137
+ end
103
138
  end
104
139
  end
105
140
  end
106
141
 
107
142
  context "from" do
108
143
  context "not converted" do
109
- let(:klass) { rebase_class from: from, to: to }
110
- let(:decoded) { decoded_from }
111
- let(:encoded) { encoded_default }
112
- it_behaves_like "values"
144
+ rebase_classes proc { { from: from, to: to } } do
145
+ let(:decoded) { decoded_from }
146
+ let(:encoded) { encoded_default }
147
+ it_behaves_like "values", @with_accessors
148
+ end
113
149
  end
114
150
 
115
151
  context "converted" do
116
- let(:klass) { rebase_class from: from, to: to, convert: convert_name, deconvert: deconvert }
117
- let(:decoded) { decoded_from }
118
- let(:encoded) { encoded_convert }
119
- it_behaves_like "values"
152
+ rebase_classes proc { { from: from, to: to, convert: convert_name, deconvert: deconvert } } do
153
+ let(:decoded) { decoded_from }
154
+ let(:encoded) { encoded_convert }
155
+ it_behaves_like "values", @with_accessors
156
+ end
120
157
  end
121
158
  end
122
159
  end
@@ -129,33 +166,37 @@ describe RebaseAttr::Generator do
129
166
  context "readable" do # 0 => x, 1 => y, l => w, o => z
130
167
  context "without from" do
131
168
  context "not converted" do
132
- let(:klass) { rebase_class to: to, readable: true }
133
- let(:decoded) { decoded_default }
134
- let(:encoded) { encoded_readable }
135
- it_behaves_like "values"
169
+ rebase_classes proc { { to: to, readable: true } } do
170
+ let(:decoded) { decoded_default }
171
+ let(:encoded) { encoded_readable }
172
+ it_behaves_like "values", @with_accessors
173
+ end
136
174
  end
137
175
 
138
176
  context "converted" do
139
- let(:klass) { rebase_class to: to, readable: true, convert: convert_name, deconvert: deconvert }
140
- let(:decoded) { decoded_default }
141
- let(:encoded) { encoded_convert_readable }
142
- it_behaves_like "values"
177
+ rebase_classes proc { { to: to, readable: true, convert: convert_name, deconvert: deconvert } } do
178
+ let(:decoded) { decoded_default }
179
+ let(:encoded) { encoded_convert_readable }
180
+ it_behaves_like "values", @with_accessors
181
+ end
143
182
  end
144
183
  end
145
184
 
146
185
  context "from" do
147
186
  context "not converted" do
148
- let(:klass) { rebase_class from: from, to: to, readable: true }
149
- let(:decoded) { decoded_from }
150
- let(:encoded) { encoded_readable }
151
- it_behaves_like "values"
187
+ rebase_classes proc { { from: from, to: to, readable: true } } do
188
+ let(:decoded) { decoded_from }
189
+ let(:encoded) { encoded_readable }
190
+ it_behaves_like "values", @with_accessors
191
+ end
152
192
  end
153
193
 
154
194
  context "converted" do
155
- let(:klass) { rebase_class from: from, to: to, readable: true, convert: convert_name, deconvert: deconvert }
156
- let(:decoded) { decoded_from }
157
- let(:encoded) { encoded_convert_readable }
158
- it_behaves_like "values"
195
+ rebase_classes proc { { from: from, to: to, readable: true, convert: convert_name, deconvert: deconvert } } do
196
+ let(:decoded) { decoded_from }
197
+ let(:encoded) { encoded_convert_readable }
198
+ it_behaves_like "values", @with_accessors
199
+ end
159
200
  end
160
201
  end
161
202
  end
@@ -235,26 +276,27 @@ describe RebaseAttr::Generator do
235
276
  specify { expect { rebase_class(to: 33, readable: true) }.to raise_error(ArgumentError, "#rebase_attr does not allow :readable option with bases higher than 32, 33 given") }
236
277
 
237
278
  context "input" do
238
- let(:klass) { rebase_class(to: 16) }
239
- let(:instance) { klass.new }
279
+ rebase_classes proc { { to: 16 } } do
280
+ let(:instance) { klass.new }
240
281
 
241
- describe "#encode" do
242
- specify { expect { klass.encode_x(:a) }.to raise_error(TypeError, "decoded value must implement #to_i, :a given") }
243
- specify { expect { instance.encode_x(:a) }.to raise_error(TypeError, "decoded value must implement #to_i, :a given") }
244
- end
282
+ describe "#encode" do
283
+ specify { expect { klass.encode_x(:a) }.to raise_error(TypeError, "decoded value must implement #to_i, :a given") }
284
+ specify { expect { instance.encode_x(:a) }.to raise_error(TypeError, "decoded value must implement #to_i, :a given") }
285
+ end
245
286
 
246
- describe "#decode" do
247
- specify { expect { klass.decode_x(:a) }.to raise_error(TypeError, "encoded value must implement #to_i, :a given") }
248
- specify { expect { instance.decode_x(:a) }.to raise_error(TypeError, "encoded value must implement #to_i, :a given") }
249
- end
287
+ describe "#decode" do
288
+ specify { expect { klass.decode_x(:a) }.to raise_error(TypeError, "encoded value must implement #to_i, :a given") }
289
+ specify { expect { instance.decode_x(:a) }.to raise_error(TypeError, "encoded value must implement #to_i, :a given") }
290
+ end
250
291
 
251
- describe "reader" do
252
- before { instance.instance_eval { @x = :a } }
253
- specify { expect { instance.x }.to raise_error(TypeError, "decoded value must implement #to_i, :a given") }
254
- end
292
+ describe "reader" do
293
+ before { instance.instance_eval { @x = :a } }
294
+ specify { expect { instance.x }.to raise_error(TypeError, "decoded value must implement #to_i, :a given") }
295
+ end
255
296
 
256
- describe "writer" do
257
- specify { expect { instance.x = :a }.to raise_error(TypeError, "encoded value must implement #to_i, :a given") }
297
+ describe "writer" do
298
+ specify { expect { instance.x = :a }.to raise_error(TypeError, "encoded value must implement #to_i, :a given") }
299
+ end
258
300
  end
259
301
  end
260
302
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rebase_attr
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oded Niv
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-25 00:00:00.000000000 Z
11
+ date: 2014-11-17 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: generate_method
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement