has_metadata 1.1.0 → 1.1.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.
data/README.textile CHANGED
@@ -1,7 +1,7 @@
1
1
  h1. has_metadata -- Keep your tables narrow
2
2
 
3
3
  | *Author* | Tim Morgan |
4
- | *Version* | 1.1 (Nov 16, 2010) |
4
+ | *Version* | 1.1.1 (Nov 21, 2010) |
5
5
  | *License* | Released under the MIT License. |
6
6
 
7
7
  h2. Important note for those upgrading from 1.0 to 1.1
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.1.1
data/has_metadata.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{has_metadata}
8
- s.version = "1.1.0"
8
+ s.version = "1.1.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tim Morgan"]
12
- s.date = %q{2010-11-17}
12
+ s.date = %q{2010-11-21}
13
13
  s.description = %q{has_metadata lets you move non-indexed and weighty columns off of your big tables by creating a separate metadata table to store all this extra information. Works with Ruby 1.9. and Rails 3.0.}
14
14
  s.email = %q{git@timothymorgan.info}
15
15
  s.extra_rdoc_files = [
@@ -16,12 +16,46 @@ module HasMetadata
16
16
 
17
17
  # @private
18
18
  def set_fields(fields)
19
- return self if @fields_set
20
- @fields_set = true
21
-
22
- fields.each do |name, _|
23
- singleton_class.send(:define_method, name) { |default=nil| data.include?(name) ? data[name] : default }
24
- singleton_class.send(:define_method, :"#{name}=") { |value| data[name] = value }
19
+ return self if @_fields_set
20
+ @_fields_set = true
21
+
22
+ singleton_class.send(:define_method, :attribute_method?) do |name|
23
+ name = name.to_sym
24
+ super(name) or fields.include?(name)
25
+ end
26
+
27
+ # override attribute prefix/suffix methods to get full first-class
28
+ # property functionality
29
+
30
+ singleton_class.send(:define_method, :attribute) do |name|
31
+ name = name.to_sym
32
+ super(name) unless fields.include?(name)
33
+
34
+ default = (fields[name].kind_of?(Hash) && fields[name][:default]) ? fields[name][:default] : nil
35
+ data.include?(name) ? data[name] : default
36
+ end
37
+ singleton_class.send :alias_method, :attribute_before_type_cast, :attribute
38
+
39
+ singleton_class.send(:define_method, :query_attribute) do |name|
40
+ name = name.to_sym
41
+ super(name) unless fields.include?(name)
42
+
43
+ if fields[name].kind_of?(Hash) and fields[name].include?(:type) then
44
+ if fields[name][:type].ancestors.include?(Numeric) then
45
+ not send(name).zero?
46
+ else
47
+ not send(name).blank?
48
+ end
49
+ else
50
+ not send(name).blank?
51
+ end
52
+ end
53
+
54
+ singleton_class.send(:define_method, :attribute=) do |name, value|
55
+ name = name.to_sym
56
+ super(name, value) unless fields.include?(name)
57
+
58
+ data[name] = value
25
59
  end
26
60
 
27
61
  self
@@ -37,4 +71,4 @@ module HasMetadata
37
71
  data.each { |key, value| data[key] = nil if data[key].blank? }
38
72
  end
39
73
  end
40
- end
74
+ end
data/lib/has_metadata.rb CHANGED
@@ -52,23 +52,19 @@ module HasMetadata
52
52
  #define_method(:metadata_changed?) { metadata and metadata.changed? }
53
53
 
54
54
  fields.each do |name, options|
55
- delegate :"#{name}=", to: :metadata!
55
+ # delegate all attribute methods to the metadata
56
+ attribute_method_matchers.each { |matcher| delegate matcher.method_name(name), to: :metadata! }
56
57
 
57
58
  if options.kind_of?(Hash) then
58
- default = options.delete(:default)
59
- define_method(name) { metadata!.send(name, default) }
59
+ type = options.delete(:type)
60
+ options.delete :default
60
61
 
61
- unless options.empty?
62
- type = options.delete(:type)
63
- validate do |obj|
64
- errors.add(name, :incorrect_type) unless
65
- metadata_typecast(obj.send(name), type).kind_of?(type) or
66
- ((options[:allow_nil] and obj.send(name).nil?) or (options[:allow_blank] and obj.send(name).blank?))
67
- end if type
68
- validates(name, options) unless options.empty? or (options.keys - [ :allow_nil, :allow_blank ]).empty?
69
- end
70
- else
71
- delegate name, to: :metadata!
62
+ validate do |obj|
63
+ errors.add(name, :incorrect_type) unless
64
+ metadata_typecast(obj.send(name), type).kind_of?(type) or
65
+ ((options[:allow_nil] and obj.send(name).nil?) or (options[:allow_blank] and obj.send(name).blank?))
66
+ end if type
67
+ validates(name, options) unless options.empty? or (options.keys - [ :allow_nil, :allow_blank ]).empty?
72
68
  end
73
69
  end
74
70
  end
@@ -13,7 +13,7 @@ module SpecSupport
13
13
  untyped: {},
14
14
  can_be_nil: { type: Date, allow_nil: true },
15
15
  can_be_blank: { type: Date, allow_blank: true },
16
- number: { numericality: true },
16
+ number: { type: Fixnum, numericality: true },
17
17
  multiparam: { type: SpecSupport::ConstructorTester },
18
18
  has_default: { default: 'default' }
19
19
  })
@@ -30,46 +30,44 @@ describe HasMetadata do
30
30
  SpecSupport::HasMetadataTester.nested_attributes_options[:metadata].should_not be_nil
31
31
  end
32
32
 
33
- it "should make a getter for each field" do
34
- SpecSupport::HasMetadataTester.new.should respond_to(:untyped)
35
- SpecSupport::HasMetadataTester.new.should respond_to(:multiparam)
36
- SpecSupport::HasMetadataTester.new.should respond_to(:number)
37
- end
38
-
39
- context "getters" do
40
- before :each do
41
- @object = SpecSupport::HasMetadataTester.new
42
- @metadata = @object.metadata!
43
- end
44
-
45
- it "should return a field in the metadata object" do
46
- @metadata.data[:untyped] = 'bar'
47
- @object.untyped.should eql('bar')
33
+ it "should define methods for each field" do
34
+ [ :attribute, :attribute_before_type_cast, :attribute= ].each do |meth|
35
+ SpecSupport::HasMetadataTester.new.should respond_to(meth.to_s.sub('attribute', 'untyped'))
36
+ SpecSupport::HasMetadataTester.new.should respond_to(meth.to_s.sub('attribute', 'multiparam'))
37
+ SpecSupport::HasMetadataTester.new.should respond_to(meth.to_s.sub('attribute', 'number'))
48
38
  end
39
+ end
49
40
 
50
- it "should return nil if there is no associated metadata" do
51
- @object.stub!(:metadata).and_return(nil)
52
- ivars = @object.instance_variables - [ :@metadata ]
53
- @object.stub!(:instance_variables).and_return(ivars)
54
-
55
- @object.untyped.should be_nil
56
- end
41
+ [ :attribute, :attribute_before_type_cast ].each do |getter|
42
+ describe "##{getter}" do
43
+ before :each do
44
+ @object = SpecSupport::HasMetadataTester.new
45
+ @metadata = @object.metadata!
46
+ end
47
+
48
+ it "should return a field in the metadata object" do
49
+ @metadata.data[:untyped] = 'bar'
50
+ @object.send(getter.to_s.sub('attribute', 'untyped')).should eql('bar')
51
+ end
52
+
53
+ it "should return nil if there is no associated metadata" do
54
+ @object.stub!(:metadata).and_return(nil)
55
+ ivars = @object.instance_variables - [ :@metadata ]
56
+ @object.stub!(:instance_variables).and_return(ivars)
57
+
58
+ @object.send(getter.to_s.sub('attribute', 'untyped')).should be_nil
59
+ end
57
60
 
58
- it "should return a default if one is specified" do
59
- @object.has_default.should eql('default')
60
- end
61
+ it "should return a default if one is specified" do
62
+ @object.send(getter.to_s.sub('attribute', 'has_default')).should eql('default')
63
+ end
61
64
 
62
- it "should return nil if nil is stored and the default is not nil" do
63
- @metadata.data[:has_default] = nil
64
- @object.has_default.should eql(nil)
65
+ it "should return nil if nil is stored and the default is not nil" do
66
+ @metadata.data[:has_default] = nil
67
+ @object.send(getter.to_s.sub('attribute', 'has_default')).should eql(nil)
68
+ end
65
69
  end
66
70
  end
67
-
68
- it "should make a setter for each field" do
69
- SpecSupport::HasMetadataTester.new.should respond_to(:untyped=)
70
- SpecSupport::HasMetadataTester.new.should respond_to(:multiparam=)
71
- SpecSupport::HasMetadataTester.new.should respond_to(:number=)
72
- end
73
71
 
74
72
  context "setters" do
75
73
  before :each do
@@ -131,5 +129,51 @@ describe HasMetadata do
131
129
  @object.multiparam.args.should eql([ 1982, 10.5 ])
132
130
  end
133
131
  end
132
+
133
+ describe "#attribute?" do
134
+ before :each do
135
+ @object = SpecSupport::HasMetadataTester.new
136
+ @metadata = @object.metadata!
137
+ end
138
+
139
+ context "untyped field" do
140
+ it "should return true if the string is not blank" do
141
+ @metadata.data = { untyped: 'foo' }
142
+ @object.untyped?.should be_true
143
+ end
144
+
145
+ it "should return false if the string is blank" do
146
+ @metadata.data = { untyped: ' ' }
147
+ @object.untyped?.should be_false
148
+
149
+ @metadata.data = { untyped: '' }
150
+ @object.untyped?.should be_false
151
+ end
152
+ end
153
+
154
+ context "numeric field" do
155
+ it "should return true if the number is not zero" do
156
+ @metadata.data = { number: 4 }
157
+ @object.number?.should be_true
158
+ end
159
+
160
+ it "should return false if the number is zero" do
161
+ @metadata.data = { number: 0 }
162
+ @object.number?.should be_false
163
+ end
164
+ end
165
+
166
+ context "typed, non-numeric field" do
167
+ it "should return true if the string is not blank" do
168
+ @metadata.data = { can_be_nil: Date.today }
169
+ @object.can_be_nil?.should be_true
170
+ end
171
+
172
+ it "should return false if the string is blank" do
173
+ @metadata.data = { can_be_nil: nil }
174
+ @object.can_be_nil?.should be_false
175
+ end
176
+ end
177
+ end
134
178
  end
135
179
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 1
8
- - 0
9
- version: 1.1.0
8
+ - 1
9
+ version: 1.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Tim Morgan
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-17 00:00:00 -08:00
17
+ date: 2010-11-21 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency