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: 6afeb6ff2bb89ff627f8705a5e7006db18f056f2
4
- data.tar.gz: 502372b9082fb76972f43abc216d4cc8d95c4be2
3
+ metadata.gz: 542197f677322bd49dc623661de6f72adae6e259
4
+ data.tar.gz: 8612b393a7cbc50203a8848c9928dfade4776ef2
5
5
  SHA512:
6
- metadata.gz: 0218e36856f3c37c08c0997f349ab7c610b528a1de19dd9bf24d312559922648a5ac9271fba86696254911688a51b62c0ee11500ed6b4af4d392834cda115126
7
- data.tar.gz: cc586d21280e82597c3cdd11390737ca7286997fc87f6cdac785749fcda3754b10fdd9174eea633da2078dca0605c6b00fa2ec35e44f7e72da314eab6247632f
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
- self.send("#{column.name}_without_type_casting=", column.cast(value))
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
 
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module TypedStore
3
- VERSION = '0.1.0'
3
+ VERSION = '0.2.0'
4
4
  end
5
5
  end
@@ -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.1.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-03 00:00:00.000000000 Z
11
+ date: 2013-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord