property_sets 0.6.2 → 0.7.1

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.
@@ -49,6 +49,7 @@ module PropertySets
49
49
  define_method "#{key}=" do |value|
50
50
  instance = lookup(key)
51
51
  instance.value = PropertySets::Casting.write(property_class.type(key), value)
52
+ instance.value
52
53
  end
53
54
 
54
55
  define_method "#{key}_record" do
@@ -56,6 +57,10 @@ module PropertySets
56
57
  end
57
58
  end
58
59
 
60
+ define_method :property_serialized? do |key|
61
+ property_class.type(key) == :serialized
62
+ end
63
+
59
64
  def save(*args)
60
65
  each { |p| p.save(*args) }
61
66
  end
@@ -88,6 +93,7 @@ module PropertySets
88
93
  def lookup(arg)
89
94
  instance = lookup_without_default(arg)
90
95
  instance ||= build_default(arg)
96
+ instance.value_serialized = property_serialized?(arg)
91
97
 
92
98
  if ActiveRecord::VERSION::MAJOR == 3
93
99
  owner = proxy_association.owner
@@ -102,7 +108,7 @@ module PropertySets
102
108
  # This finder method returns the property if present, otherwise a new instance with the default value.
103
109
  # It does not have the side effect of adding a new setting object.
104
110
  def lookup_or_default(arg)
105
- instance = detect { |property| property.name.to_sym == arg.to_sym }
111
+ instance = lookup_without_default(arg)
106
112
  instance ||= begin
107
113
  if ActiveRecord::VERSION::MAJOR == 3
108
114
  association_class = proxy_association.klass
@@ -111,6 +117,8 @@ module PropertySets
111
117
  end
112
118
  association_class.new(:value => default(arg))
113
119
  end
120
+ instance.value_serialized = property_serialized?(arg)
121
+ instance
114
122
  end
115
123
  end
116
124
  end
@@ -1,3 +1,5 @@
1
+ require 'json'
2
+
1
3
  module PropertySets
2
4
  module Casting
3
5
 
@@ -15,6 +17,9 @@ module PropertySets
15
17
  value.to_i
16
18
  when :boolean
17
19
  ![ "false", "0", "", "off", "n" ].member?(value.to_s.downcase)
20
+ when :serialized
21
+ # deserialization happens in the model
22
+ value
18
23
  end
19
24
  end
20
25
 
@@ -28,6 +33,9 @@ module PropertySets
28
33
  else
29
34
  value.in_time_zone("UTC").to_s
30
35
  end
36
+ when :serialized
37
+ # write the object directly.
38
+ value
31
39
  else
32
40
  value.to_s
33
41
  end
@@ -24,10 +24,36 @@ module PropertySets
24
24
  self.class.protected?(name.to_sym)
25
25
  end
26
26
 
27
+ def value
28
+ if value_serialized
29
+ v = read_attribute(:value)
30
+ return nil if v == "null"
31
+ @deserialized_value ||= JSON.parse(v)
32
+ else
33
+ super
34
+ end
35
+ end
36
+
37
+ def value=(v)
38
+ if value_serialized
39
+ @deserialized_value = v
40
+ write_attribute(:value, v.to_json)
41
+ else
42
+ super(v)
43
+ end
44
+ end
45
+
46
+ def reload(*args, &block)
47
+ @deserialized_value = nil
48
+ super
49
+ end
50
+
27
51
  def to_s
28
52
  value.to_s
29
53
  end
30
54
 
55
+ attr_accessor :value_serialized
56
+
31
57
  private
32
58
 
33
59
  def validate_format_of_name
@@ -38,10 +64,17 @@ module PropertySets
38
64
  end
39
65
  end
40
66
 
41
- def coerce_value
42
- self.value = value.to_s unless value.nil?
67
+ def validate_length_of_serialized_data
68
+ if value_serialized && self.read_attribute(:value).to_s.size > self.class.columns_hash["value"].limit
69
+ errors.add(:value, :invalid)
70
+ end
43
71
  end
44
72
 
73
+ def coerce_value
74
+ if value && !value_serialized
75
+ self.value = value.to_s
76
+ end
77
+ end
45
78
 
46
79
  def owner_class_instance
47
80
  send(self.class.owner_class_sym)
@@ -51,6 +84,7 @@ module PropertySets
51
84
  module ClassMethods
52
85
  def self.extended(base)
53
86
  base.validate :validate_format_of_name
87
+ base.validate :validate_length_of_serialized_data
54
88
  base.before_create :coerce_value
55
89
  end
56
90
 
data/lib/property_sets.rb CHANGED
@@ -3,7 +3,7 @@ require 'property_sets/active_record_extension'
3
3
  require 'property_sets/action_view_extension'
4
4
 
5
5
  module PropertySets
6
- VERSION = "0.6.2"
6
+ VERSION = "0.7.1"
7
7
 
8
8
  def self.ensure_property_set_class(association, owner_class)
9
9
  const_name = "#{owner_class.name}#{association.to_s.singularize.capitalize}".to_sym
@@ -13,8 +13,8 @@ Gem::Specification.new do |s|
13
13
  ## If your rubyforge_project name is different, then edit it and comment out
14
14
  ## the sub! line in the Rakefile
15
15
  s.name = 'property_sets'
16
- s.version = '0.6.2'
17
- s.date = '2012-03-22'
16
+ s.version = '0.7.1'
17
+ s.date = '2012-04-09'
18
18
  s.rubyforge_project = 'property_sets'
19
19
 
20
20
  ## Make sure your summary is short. The description may be as long
@@ -50,6 +50,7 @@ Gem::Specification.new do |s|
50
50
  s.add_runtime_dependency("activesupport", ">= 2.3.14", "< 3.3")
51
51
  s.add_runtime_dependency("activerecord", ">= 2.3.14", "< 3.3")
52
52
  s.add_runtime_dependency("actionpack", ">= 2.3.14", "< 3.3")
53
+ s.add_runtime_dependency("json")
53
54
 
54
55
  ## List your development dependencies here. Development dependencies are
55
56
  ## those that are only needed during development
data/test/helper.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
2
4
  require 'active_support'
3
5
  require 'test/unit'
4
6
  require 'active_record'
@@ -69,5 +71,6 @@ class Account < ActiveRecord::Base
69
71
  property :datetime_prop, :type => :datetime
70
72
  property :float_prop, :type => :float
71
73
  property :int_prop, :type => :integer
74
+ property :serialized_prop, :type => :serialized
72
75
  end
73
76
  end
data/test/test_casting.rb CHANGED
@@ -8,6 +8,10 @@ class TestCasting < ActiveSupport::TestCase
8
8
  assert_equal nil, PropertySets::Casting.read(:string, nil)
9
9
  assert_equal nil, PropertySets::Casting.read(:hello, nil)
10
10
  end
11
+
12
+ should "leave serialized data alone" do
13
+ assert_equal [1,2,3], PropertySets::Casting.read(:serialized, [1, 2, 3])
14
+ end
11
15
  end
12
16
 
13
17
  context "Casting#write" do
@@ -24,6 +28,11 @@ class TestCasting < ActiveSupport::TestCase
24
28
  should "convert integers to strings" do
25
29
  assert_equal "123", PropertySets::Casting.write(:integer, 123)
26
30
  end
31
+
32
+ should "leave serialized data alone for the record to deal with" do
33
+ a = [123]
34
+ assert_equal a, PropertySets::Casting.write(:serialized, a)
35
+ end
27
36
  end
28
37
 
29
38
  end
@@ -302,6 +302,34 @@ class TestPropertySets < ActiveSupport::TestCase
302
302
  assert_equal string_rep, @account.typed_data.lookup("datetime_prop").value
303
303
  end
304
304
  end
305
+
306
+ context "serialized data" do
307
+ should "store data in json" do
308
+ value = {:a => 1, :b => 2}
309
+ @account.typed_data.serialized_prop = value
310
+ @account.save!
311
+ @account.reload
312
+ assert_equal({'a' => 1, 'b' => 2}, @account.typed_data.serialized_prop)
313
+ end
314
+
315
+ should "not overflow the column" do
316
+ @account.typed_data.serialized_prop = (1..100_000).to_a
317
+ assert !@account.typed_data.lookup(:serialized_prop).valid?
318
+ assert !@account.save
319
+ end
320
+
321
+ should "allow for destructive operators" do
322
+ value = {:a => 1, :b => 2}
323
+ @account.typed_data.serialized_prop = value
324
+ @account.typed_data.serialized_prop[:c] = 3
325
+ assert_equal 3, @account.typed_data.serialized_prop[:c]
326
+ end
327
+
328
+ should "deal with nil values properly" do
329
+ @account.typed_data.serialized_prop = nil
330
+ @account.save!
331
+ end
332
+ end
305
333
  end
306
334
  end
307
335
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: property_sets
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
4
+ hash: 1
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 6
9
- - 2
10
- version: 0.6.2
8
+ - 7
9
+ - 1
10
+ version: 0.7.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Morten Primdahl
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-03-22 00:00:00 Z
18
+ date: 2012-04-09 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: activesupport
@@ -87,7 +87,7 @@ dependencies:
87
87
  type: :runtime
88
88
  version_requirements: *id003
89
89
  - !ruby/object:Gem::Dependency
90
- name: rake
90
+ name: json
91
91
  prerelease: false
92
92
  requirement: &id004 !ruby/object:Gem::Requirement
93
93
  none: false
@@ -98,10 +98,10 @@ dependencies:
98
98
  segments:
99
99
  - 0
100
100
  version: "0"
101
- type: :development
101
+ type: :runtime
102
102
  version_requirements: *id004
103
103
  - !ruby/object:Gem::Dependency
104
- name: bundler
104
+ name: rake
105
105
  prerelease: false
106
106
  requirement: &id005 !ruby/object:Gem::Requirement
107
107
  none: false
@@ -115,7 +115,7 @@ dependencies:
115
115
  type: :development
116
116
  version_requirements: *id005
117
117
  - !ruby/object:Gem::Dependency
118
- name: shoulda
118
+ name: bundler
119
119
  prerelease: false
120
120
  requirement: &id006 !ruby/object:Gem::Requirement
121
121
  none: false
@@ -129,7 +129,7 @@ dependencies:
129
129
  type: :development
130
130
  version_requirements: *id006
131
131
  - !ruby/object:Gem::Dependency
132
- name: mocha
132
+ name: shoulda
133
133
  prerelease: false
134
134
  requirement: &id007 !ruby/object:Gem::Requirement
135
135
  none: false
@@ -143,7 +143,7 @@ dependencies:
143
143
  type: :development
144
144
  version_requirements: *id007
145
145
  - !ruby/object:Gem::Dependency
146
- name: appraisal
146
+ name: mocha
147
147
  prerelease: false
148
148
  requirement: &id008 !ruby/object:Gem::Requirement
149
149
  none: false
@@ -156,6 +156,20 @@ dependencies:
156
156
  version: "0"
157
157
  type: :development
158
158
  version_requirements: *id008
159
+ - !ruby/object:Gem::Dependency
160
+ name: appraisal
161
+ prerelease: false
162
+ requirement: &id009 !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ hash: 3
168
+ segments:
169
+ - 0
170
+ version: "0"
171
+ type: :development
172
+ version_requirements: *id009
159
173
  description: This gem is an ActiveRecord extension which provides a convenient interface for managing per row properties.
160
174
  email: primdahl@me.com
161
175
  executables: []