acts_as_splittable 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +32 -0
- data/lib/acts_as_splittable/splittable.rb +84 -0
- data/lib/acts_as_splittable/version.rb +1 -1
- data/lib/acts_as_splittable.rb +60 -59
- data/spec/models/splittable_spec.rb +111 -1
- data/spec/models.rb +23 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0398f1488b36c65e7f0573f2b0c1e8b103e2c0cd
|
4
|
+
data.tar.gz: ebc482f510f36b2d4e96b52bb2a658afdab6f1dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2a3c47fe22bf41f4d68cc895ac283f0ea6b1b0ed8aac4e642069cf5ccaec769ff497d3e8eabb2f61309e4c057ae07daaade3a88e5ba3ae5416e0dd7e79f04ab
|
7
|
+
data.tar.gz: dfd523946987d69389c3a3580b176aa28b3bc294b548ecc0c5f198e5a684c3777c3f658c28f19f4d59666c2ccae9b9ab81c3ec87ab58f895a11f69f9190cf6d6
|
data/README.md
CHANGED
@@ -139,6 +139,38 @@ p splittable.email_local #=> "splittable"
|
|
139
139
|
p splittable.email_domain #=> "example.com"
|
140
140
|
```
|
141
141
|
|
142
|
+
### Automatically (without callbacks)
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
class Splittable < ActiveRecord::Base
|
146
|
+
|
147
|
+
acts_as_splittable split_on_change: true, join_on_change: true, callbacks: false
|
148
|
+
|
149
|
+
# ...
|
150
|
+
end
|
151
|
+
```
|
152
|
+
|
153
|
+
then
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
splittable = Splittable.new(
|
157
|
+
email_local: 'splittable',
|
158
|
+
email_domain: 'example.com',
|
159
|
+
)
|
160
|
+
|
161
|
+
p splittable.email #=> "splittable@example.com"
|
162
|
+
p splittable.valid? #=> true
|
163
|
+
```
|
164
|
+
|
165
|
+
and
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
splittable = Splittable.find(splittable_id)
|
169
|
+
|
170
|
+
p splittable.email_local #=> "splittable"
|
171
|
+
p splittable.email_domain #=> "example.com"
|
172
|
+
```
|
173
|
+
|
142
174
|
Contributing
|
143
175
|
--------------------
|
144
176
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module ActsAsSplittable
|
2
|
+
|
3
|
+
module Splittable
|
4
|
+
|
5
|
+
def split_column_values!(column = nil)
|
6
|
+
if column.nil?
|
7
|
+
self.class.splittable_columns.each_key{|key| send __method__, key }
|
8
|
+
else
|
9
|
+
column = column.to_sym
|
10
|
+
split, pattern, partials, on_split, on_join = self.class.splittable_columns[column]
|
11
|
+
value = send(column)
|
12
|
+
|
13
|
+
unless value.nil?
|
14
|
+
values = if on_split
|
15
|
+
splittable_run_callback(on_split, value)
|
16
|
+
elsif value
|
17
|
+
if split
|
18
|
+
value.to_s.split *(split.is_a?(Array) ? split : [split])
|
19
|
+
elsif matches = value.to_s.match(pattern)
|
20
|
+
matches[1..(matches.length - 1)]
|
21
|
+
end
|
22
|
+
end || []
|
23
|
+
|
24
|
+
partials.each_with_index do |partial, index|
|
25
|
+
send :"#{partial}=", values[index]
|
26
|
+
end
|
27
|
+
|
28
|
+
reset_splittable_changed_partials partials
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def join_column_values!(column = nil)
|
36
|
+
if column.nil?
|
37
|
+
self.class.splittable_columns.each_key{|key| send __method__, key }
|
38
|
+
else
|
39
|
+
split, pattern, partials, on_split, on_join = self.class.splittable_columns[column.to_sym]
|
40
|
+
values = partials.map{|partial| send(partial) }
|
41
|
+
|
42
|
+
unless values.any?(&:nil?)
|
43
|
+
send :"#{column}=", splittable_run_callback(on_join, values)
|
44
|
+
reset_splittable_changed_partials partials
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def splittable_partials
|
52
|
+
@splittable_partials ||= {}
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
attr_writer :splittable_changed_partials
|
58
|
+
|
59
|
+
def splittable_changed_partials
|
60
|
+
@splittable_changed_partials ||= []
|
61
|
+
end
|
62
|
+
|
63
|
+
def splittable_changed_partial?(partial)
|
64
|
+
splittable_changed_partials.include? partial
|
65
|
+
end
|
66
|
+
|
67
|
+
def reset_splittable_changed_partials(partials)
|
68
|
+
self.splittable_changed_partials.uniq!
|
69
|
+
self.splittable_changed_partials -= partials
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def splittable_run_callback(callback, *args)
|
75
|
+
if callback.is_a?(Proc)
|
76
|
+
instance_exec(*args, &callback)
|
77
|
+
else
|
78
|
+
send(callback, *args)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/lib/acts_as_splittable.rb
CHANGED
@@ -1,16 +1,28 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
2
|
+
|
1
3
|
require 'active_record'
|
4
|
+
require 'acts_as_splittable/splittable'
|
2
5
|
|
3
6
|
module ActsAsSplittable
|
4
7
|
|
5
8
|
def acts_as_splittable(options = {})
|
6
|
-
options.reverse_merge!(
|
7
|
-
callbacks:
|
9
|
+
options = options.reverse_merge!(
|
10
|
+
callbacks: true,
|
11
|
+
predicates: false,
|
12
|
+
join_on_change: false,
|
13
|
+
split_on_change: false,
|
8
14
|
)
|
9
15
|
|
10
16
|
extend ClassMethods
|
11
|
-
include
|
17
|
+
include Splittable
|
18
|
+
|
19
|
+
self.splittable_options = options
|
12
20
|
|
13
|
-
if
|
21
|
+
if splittable_options[:split_on_change]
|
22
|
+
include splittable_module
|
23
|
+
end
|
24
|
+
|
25
|
+
if splittable_options[:callbacks]
|
14
26
|
after_initialize { new_record? or split_column_values! }
|
15
27
|
before_save { join_column_values! }
|
16
28
|
end
|
@@ -19,6 +31,19 @@ module ActsAsSplittable
|
|
19
31
|
module ClassMethods
|
20
32
|
SPLITTABLE_DEFAULT_JOIN_PROCESS = Proc.new{|values| values.join }
|
21
33
|
|
34
|
+
attr_writer :splittable_options
|
35
|
+
|
36
|
+
def splittable_options(other_options = {})
|
37
|
+
@splittable_options ||= {}
|
38
|
+
end
|
39
|
+
|
40
|
+
def with_splittable_options(other_options = {})
|
41
|
+
original_options = splittable_options
|
42
|
+
self.splittable_options = splittable_options.merge(other_options)
|
43
|
+
Proc.new.(splittable_options)
|
44
|
+
self.splittable_options = original_options
|
45
|
+
end
|
46
|
+
|
22
47
|
def splittable_columns
|
23
48
|
@splittable_columns ||= {}
|
24
49
|
end
|
@@ -35,75 +60,51 @@ module ActsAsSplittable
|
|
35
60
|
|
36
61
|
define_method :"#{partial}=" do |value|
|
37
62
|
splittable_partials[partial] = value
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def inherited(child)
|
43
|
-
super
|
44
|
-
child.splittable_columns.merge! splittable_columns.dup
|
45
|
-
end
|
46
|
-
end
|
63
|
+
splittable_changed_partials << partial unless splittable_changed_partial? partial
|
47
64
|
|
48
|
-
|
49
|
-
|
50
|
-
if column.nil?
|
51
|
-
self.class.splittable_columns.each_key{|key| send __method__, key }
|
52
|
-
else
|
53
|
-
column = column.to_sym
|
54
|
-
split, pattern, partials, on_split, on_join = self.class.splittable_columns[column]
|
55
|
-
value = send(column)
|
56
|
-
|
57
|
-
unless value.nil?
|
58
|
-
values = if on_split
|
59
|
-
run_callback(on_split, value)
|
60
|
-
elsif value
|
61
|
-
if split
|
62
|
-
value.to_s.split *(split.is_a?(Array) ? split : [split])
|
63
|
-
else
|
64
|
-
matches = value.to_s.match(pattern)
|
65
|
-
matches[1..(matches.length - 1)]
|
66
|
-
end
|
67
|
-
end || []
|
68
|
-
|
69
|
-
partials.each_with_index do |partial, index|
|
70
|
-
send :"#{partial}=", values[index]
|
65
|
+
self.class.with_splittable_options split_on_change: false do |options|
|
66
|
+
join_column_values! column if options[:join_on_change]
|
71
67
|
end
|
72
68
|
end
|
73
|
-
end
|
74
|
-
|
75
|
-
self
|
76
|
-
end
|
77
69
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
split, pattern, partials, on_split, on_join = self.class.splittable_columns[column.to_sym]
|
83
|
-
partials = partials.map{|partial| send(partial) }
|
84
|
-
|
85
|
-
unless partials.any?(&:nil?)
|
86
|
-
send :"#{column}=", run_callback(on_join, partials)
|
70
|
+
if splittable_options[:predicates]
|
71
|
+
define_method :"#{partial}_changed?" do
|
72
|
+
splittable_changed_partial? partial
|
73
|
+
end
|
87
74
|
end
|
88
75
|
end
|
89
76
|
|
90
|
-
|
77
|
+
if splittable_options[:split_on_change]
|
78
|
+
splittable_module.module_eval <<-"EOS"
|
79
|
+
def #{column}=(value)
|
80
|
+
if defined?(super)
|
81
|
+
super
|
82
|
+
elsif respond_to?(:write_attribute, true)
|
83
|
+
write_attribute :#{column}, value
|
84
|
+
end
|
85
|
+
|
86
|
+
self.class.with_splittable_options join_on_change: false do
|
87
|
+
split_column_values! :#{column}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
EOS
|
91
|
+
end
|
91
92
|
end
|
92
93
|
|
93
|
-
def
|
94
|
-
|
94
|
+
def inherited(child)
|
95
|
+
super
|
96
|
+
|
97
|
+
child.splittable_options = splittable_options.dup
|
98
|
+
child.splittable_columns.merge! splittable_columns.dup
|
95
99
|
end
|
96
100
|
|
97
|
-
|
101
|
+
protected
|
98
102
|
|
99
|
-
def
|
100
|
-
|
101
|
-
instance_exec(*args, &callback)
|
102
|
-
else
|
103
|
-
send(callback, *args)
|
104
|
-
end
|
103
|
+
def splittable_module
|
104
|
+
@splittable_module ||= Module.new
|
105
105
|
end
|
106
106
|
end
|
107
|
+
|
107
108
|
end
|
108
109
|
|
109
110
|
ActiveRecord::Base.extend ActsAsSplittable
|
@@ -47,7 +47,7 @@ require 'spec_helper'
|
|
47
47
|
|
48
48
|
it 'should split columns after initialize' do
|
49
49
|
@splittables.each do |record|
|
50
|
-
splittable =
|
50
|
+
splittable = klass.find(record.id)
|
51
51
|
|
52
52
|
splittable.email_local.should == 'splittable'
|
53
53
|
splittable.email_domain.should == 'example.com'
|
@@ -59,6 +59,39 @@ require 'spec_helper'
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
describe '#*_changed?' do
|
63
|
+
before do
|
64
|
+
@splittable = klass.new
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should return true when value is changed until #split_column_values! or #join_column_values! is called' do
|
68
|
+
@splittable.email_local_changed?.should_not be_true
|
69
|
+
@splittable.email_domain_changed?.should_not be_true
|
70
|
+
|
71
|
+
@splittable.email_local = 'splittable'
|
72
|
+
@splittable.email_local_changed?.should be_true
|
73
|
+
|
74
|
+
@splittable.email_domain = 'example.com'
|
75
|
+
@splittable.email_domain_changed?.should be_true
|
76
|
+
|
77
|
+
@splittable.join_column_values!
|
78
|
+
|
79
|
+
@splittable.email_local_changed?.should_not be_true
|
80
|
+
@splittable.email_domain_changed?.should_not be_true
|
81
|
+
|
82
|
+
@splittable.email_local = nil
|
83
|
+
@splittable.email_local_changed?.should be_true
|
84
|
+
|
85
|
+
@splittable.email_domain = nil
|
86
|
+
@splittable.email_domain_changed?.should be_true
|
87
|
+
|
88
|
+
@splittable.split_column_values!
|
89
|
+
|
90
|
+
@splittable.email_local_changed?.should_not be_true
|
91
|
+
@splittable.email_domain_changed?.should_not be_true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
62
95
|
context 'when nil includes in partials or value of column is nil' do
|
63
96
|
before :each do
|
64
97
|
@splittable1 = klass.new(name: "#{klass.name} 1")
|
@@ -133,3 +166,80 @@ describe Splittable do
|
|
133
166
|
end
|
134
167
|
end
|
135
168
|
end
|
169
|
+
|
170
|
+
describe SplittableSplitOrJoinOnChange do
|
171
|
+
|
172
|
+
it 'should join partials when one of partials is set and all of them are not nil' do
|
173
|
+
splittable = SplittableSplitOrJoinOnChange.new
|
174
|
+
|
175
|
+
splittable.email_local = 'splittable'
|
176
|
+
splittable.email_domain = 'example.com'
|
177
|
+
|
178
|
+
splittable.email.should == 'splittable@example.com'
|
179
|
+
|
180
|
+
splittable.email = nil
|
181
|
+
|
182
|
+
splittable.phone_number1 = '012'
|
183
|
+
splittable.phone_number.should be_nil
|
184
|
+
|
185
|
+
splittable.phone_number2 = '3456'
|
186
|
+
splittable.phone_number.should be_nil
|
187
|
+
|
188
|
+
splittable.phone_number3 = '7890'
|
189
|
+
splittable.phone_number.should == '012-3456-7890'
|
190
|
+
|
191
|
+
splittable.phone_number3 = '0000'
|
192
|
+
splittable.phone_number.should == '012-3456-0000'
|
193
|
+
|
194
|
+
splittable.email.should be_nil
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should split value when value is set' do
|
198
|
+
splittable1 = SplittableSplitOrJoinOnChange.new(
|
199
|
+
email: 'splittable@example.com',
|
200
|
+
phone_number: '012-3456-7890',
|
201
|
+
)
|
202
|
+
|
203
|
+
splittable2 = SplittableSplitOrJoinOnChange.new
|
204
|
+
splittable2.email = 'splittable@example.com'
|
205
|
+
splittable2.phone_number = '012-3456-7890'
|
206
|
+
|
207
|
+
[splittable1, splittable2].each do |splittable|
|
208
|
+
splittable.email_local.should == 'splittable'
|
209
|
+
splittable.email_domain.should == 'example.com'
|
210
|
+
splittable.phone_number1.should == '012'
|
211
|
+
splittable.phone_number2.should == '3456'
|
212
|
+
splittable.phone_number3.should == '7890'
|
213
|
+
end
|
214
|
+
|
215
|
+
splittable1.phone_number = '000-0000-0000'
|
216
|
+
|
217
|
+
splittable1.phone_number1.should == '000'
|
218
|
+
splittable1.phone_number2.should == '0000'
|
219
|
+
splittable1.phone_number3.should == '0000'
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
describe SplittableSplitOrJoinOnChangeWithAliasAttribute do
|
225
|
+
|
226
|
+
it 'should split value when value is set' do
|
227
|
+
splittable1 = SplittableSplitOrJoinOnChangeWithAliasAttribute.new(
|
228
|
+
email_address: 'splittable@example.com',
|
229
|
+
)
|
230
|
+
|
231
|
+
splittable2 = SplittableSplitOrJoinOnChangeWithAliasAttribute.new
|
232
|
+
splittable2.email_address = 'splittable@example.com'
|
233
|
+
|
234
|
+
[splittable1, splittable2].each do |splittable|
|
235
|
+
splittable.email_local.should == 'splittable'
|
236
|
+
splittable.email_domain.should == 'example.com'
|
237
|
+
end
|
238
|
+
|
239
|
+
splittable1.email_address = 'splittable1@1.example.com'
|
240
|
+
|
241
|
+
splittable1.email_local.should == 'splittable1'
|
242
|
+
splittable1.email_domain.should == '1.example.com'
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
data/spec/models.rb
CHANGED
@@ -3,7 +3,7 @@ EMAIL_JOIN_PROCESS = Proc.new{|values| values.join('@') }
|
|
3
3
|
|
4
4
|
class Splittable < ActiveRecord::Base
|
5
5
|
|
6
|
-
acts_as_splittable
|
6
|
+
acts_as_splittable predicates: true
|
7
7
|
|
8
8
|
splittable :email, split: ['@', 2], partials: [:email_local, :email_domain], on_join: EMAIL_JOIN_PROCESS
|
9
9
|
splittable :postal_code, pattern: /\A(?<postal_code1>[0-9]{3})(?<postal_code2>[0-9]{4})\Z/
|
@@ -43,4 +43,26 @@ class SplittableWithValidationForOriginalColumn < ActiveRecord::Base
|
|
43
43
|
splittable :email, pattern: EMAIL_SPLIT_PATTERN, on_join: EMAIL_JOIN_PROCESS
|
44
44
|
|
45
45
|
validates :email, format: { with: /\A[a-zA-Z0-9_.-]+@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,4}\Z/ }
|
46
|
+
end
|
47
|
+
|
48
|
+
class SplittableSplitOrJoinOnChange < ActiveRecord::Base
|
49
|
+
self.table_name = 'splittables'
|
50
|
+
|
51
|
+
acts_as_splittable join_on_change: true, split_on_change: true, callbacks: false
|
52
|
+
|
53
|
+
splittable :email, pattern: EMAIL_SPLIT_PATTERN, on_join: EMAIL_JOIN_PROCESS
|
54
|
+
|
55
|
+
splittable :phone_number,
|
56
|
+
pattern: /\A(?<phone_number1>\d{3})-(?<phone_number2>\d{4})-(?<phone_number3>\d{4})\Z/,
|
57
|
+
on_join: ->(values) { values.join '-' }
|
58
|
+
end
|
59
|
+
|
60
|
+
class SplittableSplitOrJoinOnChangeWithAliasAttribute < ActiveRecord::Base
|
61
|
+
self.table_name = 'splittables'
|
62
|
+
|
63
|
+
acts_as_splittable join_on_change: true, split_on_change: true, callbacks: false
|
64
|
+
|
65
|
+
splittable :email, pattern: EMAIL_SPLIT_PATTERN, on_join: EMAIL_JOIN_PROCESS
|
66
|
+
|
67
|
+
alias_attribute :email_address, :email
|
46
68
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_splittable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tatat
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-06-
|
12
|
+
date: 2013-06-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- Rakefile
|
90
90
|
- acts_as_splittable.gemspec
|
91
91
|
- lib/acts_as_splittable.rb
|
92
|
+
- lib/acts_as_splittable/splittable.rb
|
92
93
|
- lib/acts_as_splittable/version.rb
|
93
94
|
- lib/tasks/acts_as_splittable_tasks.rake
|
94
95
|
- spec/database.yml.sample
|