attr_bucket 0.3.1 → 0.4.0

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.
@@ -1,3 +1,3 @@
1
1
  module AttrBucket
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/attr_bucket.rb CHANGED
@@ -32,9 +32,12 @@ module AttrBucket
32
32
  def attr_bucket(opts = {})
33
33
  unless include? InstanceMethods
34
34
  include InstanceMethods
35
-
36
- class_attribute :bucketed_attributes
37
- self.bucketed_attributes = []
35
+ class_attribute :_attr_bucketed_attributes
36
+ self._attr_bucketed_attributes = []
37
+ class_attribute :_attr_bucket_methods
38
+ # We define our methods on this module so we can override and super
39
+ self._attr_bucket_methods = Module.new
40
+ include self._attr_bucket_methods
38
41
  end
39
42
 
40
43
  return nil unless table_exists?
@@ -49,13 +52,11 @@ module AttrBucket
49
52
 
50
53
  if attrs.is_a?(Hash)
51
54
  attrs.map do|attr_name, attr_type|
52
- define_bucket_reader bucket_name, attr_name
53
- define_bucket_writer bucket_name, attr_name, attr_type, bucket_column.class
55
+ _define_bucket bucket_name, attr_name, attr_type, bucket_column.class
54
56
  end
55
57
  else
56
58
  Array.wrap(attrs).each do |attr_name|
57
- define_bucket_reader bucket_name, attr_name
58
- define_bucket_writer bucket_name, attr_name, :string, bucket_column.class
59
+ _define_bucket bucket_name, attr_name, :string, bucket_column.class
59
60
  end
60
61
  end
61
62
  end
@@ -63,33 +64,28 @@ module AttrBucket
63
64
 
64
65
  alias :i_has_a_bucket :attr_bucket
65
66
 
66
- def define_bucket_reader(bucket_name, attr_name) #:nodoc:
67
- self.bucketed_attributes += [attr_name.to_s]
68
- define_method attr_name do
69
- get_attr_bucket(bucket_name)[attr_name]
70
- end unless method_defined? attr_name
71
- end
67
+ def _define_bucket(bucket_name, attr_name, attr_type, column_class)
68
+ self._attr_bucketed_attributes |= [attr_name.to_s]
69
+
70
+ self._attr_bucket_methods.class_eval do
71
+ define_method attr_name do
72
+ _get_bucket(bucket_name)[attr_name]
73
+ end
72
74
 
73
- def define_bucket_writer(bucket_name, attr_name, attr_type, column_class) #:nodoc:
74
- define_method "#{attr_name}=" do |val|
75
- # TODO: Make this more resilient/granular for multiple bucketed changes
76
- send("#{bucket_name}_will_change!")
77
- typecasted = explicitly_type_cast(val, attr_type, column_class)
78
- get_attr_bucket(bucket_name)[attr_name] = typecasted
79
- end unless method_defined? "#{attr_name}="
75
+ define_method "#{attr_name}=" do |val|
76
+ send "#{bucket_name}_will_change!"
77
+ typecasted = _explicitly_type_cast(val, attr_type, column_class)
78
+ _get_bucket(bucket_name)[attr_name] = typecasted
79
+ end
80
+ end
80
81
  end
81
82
 
82
83
  module InstanceMethods
83
- # Retrieve the attribute bucket, or if it's not yet a Hash,
84
- # initialize it as one.
85
- def get_attr_bucket(name)
86
- unless self[name].is_a?(Hash)
87
- self[name] = {}
88
- end
89
- self[name]
84
+ def _get_bucket(bucket_name)
85
+ self[bucket_name] ||= {}
90
86
  end
91
87
 
92
- def valid_class(value, type)
88
+ def _valid_class?(value, type)
93
89
  case type
94
90
  when :integer then Fixnum === value
95
91
  when :float then Float === value
@@ -109,7 +105,7 @@ module AttrBucket
109
105
  # dates/times for bucketed columns and handle them ourselves
110
106
  # before passing the remainder on for ActiveRecord::Base to handle.
111
107
  def assign_multiparameter_attributes(pairs)
112
- bucket_pairs = pairs.select {|p| self.class.bucketed_attributes.include?(p.first.split('(').first)}
108
+ bucket_pairs = pairs.select {|p| self.class._attr_bucketed_attributes.include?(p.first.split('(').first)}
113
109
  extract_callstack_for_multiparameter_attributes(bucket_pairs).each do |name, value|
114
110
  send(name + '=', value.compact.empty? ? nil : value)
115
111
  end
@@ -122,7 +118,7 @@ module AttrBucket
122
118
  #
123
119
  # This allows custom typecasting by supplying a proc, etc
124
120
  # as the value side of the hash in an attr_bucket definition.
125
- def explicitly_type_cast(value, type, column_class)
121
+ def _explicitly_type_cast(value, type, column_class)
126
122
  return nil if value.nil?
127
123
 
128
124
  return type.call(value) if type.respond_to?(:call)
@@ -133,21 +129,21 @@ module AttrBucket
133
129
  when :integer then value.to_i rescue value ? 1 : 0
134
130
  when :float then value.to_f
135
131
  when :decimal then column_class.value_to_decimal(value)
136
- when :datetime then cast_to_time(value, column_class)
137
- when :timestamp then cast_to_time(value, column_class)
138
- when :time then cast_to_time(value, column_class, true)
139
- when :date then cast_to_date(value, column_class)
132
+ when :datetime then _cast_to_time(value, column_class)
133
+ when :timestamp then _cast_to_time(value, column_class)
134
+ when :time then _cast_to_time(value, column_class, true)
135
+ when :date then _cast_to_date(value, column_class)
140
136
  when :binary then column_class.binary_to_string(value)
141
137
  when :boolean then column_class.value_to_boolean(value)
142
138
  else value
143
139
  end
144
140
 
145
- raise ArgumentError, "Unable to typecast #{value} to #{type}" unless valid_class(typecasted, type)
141
+ raise ArgumentError, "Unable to typecast #{value} to #{type}" unless _valid_class?(typecasted, type)
146
142
 
147
143
  typecasted
148
144
  end
149
145
 
150
- def cast_to_date(value, column_class)
146
+ def _cast_to_date(value, column_class)
151
147
  if value.is_a?(Array)
152
148
  begin
153
149
  values = value.collect { |v| v.nil? ? 1 : v }
@@ -160,7 +156,7 @@ module AttrBucket
160
156
  end
161
157
  end
162
158
 
163
- def cast_to_time(value, column_class, dummy_time = false)
159
+ def _cast_to_time(value, column_class, dummy_time = false)
164
160
  if value.is_a?(Array)
165
161
  value[0] ||= Date.today.year
166
162
  Time.time_with_datetime_fallback(self.class.default_timezone, *value)
@@ -19,6 +19,23 @@ describe AttrBucket do
19
19
  @o = an_object_with_bucket :bucket => :nickname
20
20
  end
21
21
 
22
+ it 'should have our anonymous module for its immediate ancestor' do
23
+ mod = @o.class.ancestors[1]
24
+ mod.instance_methods(false).should include :nickname
25
+ end
26
+
27
+ it 'should not have a nickname method in its class' do
28
+ @o.class.instance_methods(false).should_not include :nickname
29
+ end
30
+
31
+ it 'should be able to override methods and use super' do
32
+ @o.nickname = 'John'
33
+ def @o.nickname
34
+ "Jimmy #{super}"
35
+ end
36
+ @o.nickname.should eq 'Jimmy John'
37
+ end
38
+
22
39
  it 'should cast nickname to string' do
23
40
  @o.nickname = 42
24
41
  @o.nickname.should eq '42'
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: attr_bucket
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.3.1
5
+ version: 0.4.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Ernie Miller
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-02-12 00:00:00 -05:00
13
+ date: 2011-02-19 00:00:00 -05:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency