acts_as_splittable 0.0.4 → 0.0.5
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.
- 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
|