activerecord-typedstore 0.1.0 → 0.2.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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 542197f677322bd49dc623661de6f72adae6e259
|
4
|
+
data.tar.gz: 8612b393a7cbc50203a8848c9928dfade4776ef2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a06189e792adec4ac11a2bc6020439135051a1d7194f21d43008d9077fcef511ddcf9f8d252f5f25478aa9220425b38bc03655462a6138b04e9e941bcfdcc566
|
7
|
+
data.tar.gz: dfc9469b4dd7c9e1dbb611db6db1e150ac643d6f52f890f58665308f384457cf5a0b2f6a7e885af51ff7db48f16d996971a3b12229bf8e226bd53a9c188c0bcb
|
data/README.md
CHANGED
@@ -66,6 +66,12 @@ shop.update_attributes(
|
|
66
66
|
shop.age # => 42
|
67
67
|
shop.published_at.class #= DateTime
|
68
68
|
|
69
|
+
# And changes are tracked
|
70
|
+
shop.age_changed? # => false
|
71
|
+
shop.age = 12
|
72
|
+
shop.age_changed? # => true
|
73
|
+
shop.age_was # => 42
|
74
|
+
|
69
75
|
# You can still use it as a regular store
|
70
76
|
shop.settings[:unknown] = 'Hello World'
|
71
77
|
shop.save
|
@@ -3,6 +3,11 @@ module ActiveRecord::TypedStore
|
|
3
3
|
module AR32Fallbacks
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
+
included do
|
7
|
+
cattr_accessor :virtual_attribute_methods
|
8
|
+
self.virtual_attribute_methods = []
|
9
|
+
end
|
10
|
+
|
6
11
|
module ClassMethods
|
7
12
|
|
8
13
|
def typed_store(store_attribute, options={}, &block)
|
@@ -12,6 +17,24 @@ module ActiveRecord::TypedStore
|
|
12
17
|
|
13
18
|
protected
|
14
19
|
|
20
|
+
def define_virtual_attribute_method(name)
|
21
|
+
virtual_attribute_methods << name
|
22
|
+
define_attribute_method(name)
|
23
|
+
end
|
24
|
+
|
25
|
+
# ActiveModel override heavilly inspired from the original code
|
26
|
+
def define_attribute_method(attr_name)
|
27
|
+
return super unless virtual_attribute_methods.include?(attr_name)
|
28
|
+
|
29
|
+
attribute_method_matchers.each do |matcher|
|
30
|
+
method_name = matcher.method_name(attr_name)
|
31
|
+
unless instance_method_already_implemented?(method_name)
|
32
|
+
define_optimized_call generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
attribute_method_matchers_cache.clear
|
36
|
+
end
|
37
|
+
|
15
38
|
def _ar_32_fallback_accessors(store_attribute, columns)
|
16
39
|
_ar_32_fallback_initializer(store_attribute, columns)
|
17
40
|
columns.each do |column|
|
@@ -39,7 +62,9 @@ module ActiveRecord::TypedStore
|
|
39
62
|
|
40
63
|
def _ar_32_fallback_writer(store_attribute, column)
|
41
64
|
define_method("#{column.name}_with_type_casting=") do |value|
|
42
|
-
|
65
|
+
casted_value = column.cast(value)
|
66
|
+
attribute_will_change!(column.name.to_s) if casted_value != send(column.name)
|
67
|
+
send("#{column.name}_without_type_casting=", casted_value)
|
43
68
|
end
|
44
69
|
alias_method_chain "#{column.name}=", :type_casting
|
45
70
|
end
|
@@ -7,6 +7,10 @@ module ActiveRecord::TypedStore
|
|
7
7
|
IS_AR_4_0 = AR_VERSION >= Gem::Version.new('4.0') && AR_VERSION < Gem::Version.new('4.1.0.beta')
|
8
8
|
IS_AR_4_1 = AR_VERSION >= Gem::Version.new('4.1.0.beta')
|
9
9
|
|
10
|
+
unless IS_AR_3_2
|
11
|
+
ActiveModel::AttributeMethods::ClassMethods.send(:alias_method, :define_virtual_attribute_method, :define_attribute_method)
|
12
|
+
end
|
13
|
+
|
10
14
|
module Extension
|
11
15
|
extend ActiveSupport::Concern
|
12
16
|
|
@@ -27,6 +31,8 @@ module ActiveRecord::TypedStore
|
|
27
31
|
stored_typed_attributes[store_attribute] ||= {}
|
28
32
|
stored_typed_attributes[store_attribute].merge!(dsl.columns.index_by(&:name))
|
29
33
|
|
34
|
+
dsl.column_names.each { |c| define_virtual_attribute_method(c.to_s) }
|
35
|
+
|
30
36
|
dsl
|
31
37
|
end
|
32
38
|
|
@@ -42,6 +48,7 @@ module ActiveRecord::TypedStore
|
|
42
48
|
end
|
43
49
|
end
|
44
50
|
|
51
|
+
attribute_will_change!(key.to_s) if casted_value != read_store_attribute(store_attribute, key)
|
45
52
|
super(store_attribute, key, casted_value)
|
46
53
|
end
|
47
54
|
|
@@ -26,6 +26,41 @@ shared_examples 'any model' do
|
|
26
26
|
|
27
27
|
end
|
28
28
|
|
29
|
+
describe 'dirty tracking' do
|
30
|
+
|
31
|
+
it 'track changed attributes' do
|
32
|
+
expect {
|
33
|
+
model.age = 24
|
34
|
+
}.to change { model.age_changed? }.from(false).to(true)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'keep track of what the attribute was' do
|
38
|
+
model.age = 24
|
39
|
+
expect(model.age_was).to be == 12
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'keep track of the whole changes' do
|
43
|
+
expect {
|
44
|
+
model.age = 24
|
45
|
+
}.to change { model.changes['age'] }.from(nil).to([12, 24])
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'reset recorded changes after successful save' do
|
49
|
+
model.age = 24
|
50
|
+
expect {
|
51
|
+
model.save
|
52
|
+
}.to change { model.age_changed? }.from(true).to(false)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'can be reset individually' do
|
56
|
+
model.age = 24
|
57
|
+
expect {
|
58
|
+
model.reset_age!
|
59
|
+
}.to change { model.age }.from(24).to(12)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
29
64
|
describe 'unknown attribute' do
|
30
65
|
|
31
66
|
it 'raise an ActiveRecord::UnknownAttributeError on save attemps' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-typedstore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|