ocean-dynamo 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -47,23 +47,40 @@ module OceanDynamo
47
47
 
48
48
  # Define accessors for instances
49
49
  self.class_eval "def #{target_attr}
50
- read_and_maybe_load_pointer('#{target_attr_id}')
50
+ @#{target_attr} ||= load_target_from_id('#{target_attr_id}')
51
51
  end"
52
52
 
53
- self.class_eval "def #{target_attr}=(value)
54
- write_attribute('#{target_attr_id}', value)
55
- @#{target_attr} = value
53
+ self.class_eval "def #{target_attr_id}
54
+ read_attribute('#{target_attr_id}')
56
55
  end"
57
56
 
58
- self.class_eval "def #{target_attr_id}
59
- get_pointer_id(@#{target_attr})
57
+ self.class_eval "def #{target_attr}=(value)
58
+ if !value
59
+ target_id = nil
60
+ target = nil
61
+ elsif !value.kind_of?(#{target_class})
62
+ raise AssociationTypeMismatch, \"can't save a #\{value.class\} in a #{target_class} foreign key\"
63
+ else
64
+ target_id = value.hash_key
65
+ target = value
66
+ end
67
+ write_attribute('#{target_attr_id}', target_id)
68
+ @#{target_attr} = target
69
+ value
60
70
  end"
61
71
 
62
72
  self.class_eval "def #{target_attr_id}=(value)
63
- write_attribute('#{target_attr_id}', value)
64
- @#{target_attr} = value
73
+ if !value
74
+ target_id = nil
75
+ elsif value.is_a?(String)
76
+ target_id = value
77
+ else
78
+ raise AssociationTypeMismatch, 'Foreign key #{target_attr_id} must be nil or a string'
79
+ end
80
+ write_attribute('#{target_attr_id}', target_id)
81
+ @#{target_attr} = nil
82
+ value
65
83
  end"
66
- # TODO: "?" methods
67
84
  end
68
85
 
69
86
 
@@ -121,40 +138,23 @@ module OceanDynamo
121
138
  end
122
139
 
123
140
 
124
- protected
125
-
126
141
  #
127
142
  # This is run by #initialize and by #assign_attributes to set the
128
- # association variables (@master, for instance) and its associated attribute
129
- # (such as master_id) to the value given. This is a hack, do away with
130
- # the double storage when association proxies are introduced.
143
+ # association instance variables (@master, for instance) and their associated
144
+ # attributes (such as master_id) from a given value.
131
145
  #
132
146
  def set_belongs_to_association(attrs) # :nodoc:
133
147
  parent_class = self.class.belongs_to_class
134
148
  return unless parent_class
135
149
  parent_class = parent_class.to_s.underscore.to_sym
136
- if attrs && attrs.include?(parent_class)
137
- instance_variable_set("@#{parent_class}", attrs[parent_class])
138
- write_attribute("#{parent_class}_id", attrs[parent_class])
139
- end
140
- end
141
-
142
-
143
- def read_and_maybe_load_pointer(name) # :nodoc:
144
- ptr = read_attribute(name)
145
- return nil if ptr.blank?
146
- if persisted? && ptr.is_a?(String)
147
- parent = fields[name][:target_class].find(ptr, consistent: true) # TODO: true?
148
- write_attribute(name, parent) # Keep the instance we've just read
149
- else
150
- ptr
151
- end
150
+ send("#{parent_class}=", attrs[parent_class]) if attrs && attrs.include?(parent_class)
152
151
  end
153
152
 
154
153
 
155
- def get_pointer_id(ptr) # :nodoc:
156
- return nil if ptr.blank?
157
- ptr.is_a?(String) ? ptr : ptr.id
154
+ def load_target_from_id(name) # :nodoc:
155
+ v = read_attribute(name)
156
+ return nil unless v
157
+ fields[name][:target_class].find(v, consistent: true)
158
158
  end
159
159
 
160
160
  end
@@ -22,8 +22,10 @@ module OceanDynamo
22
22
  children_attr = children.to_s.underscore # "children"
23
23
  child_class = children_attr.singularize.camelize.constantize # Child
24
24
  register_relation(child_class, :has_many)
25
+ attr_accessor children_attr
25
26
  # Define accessors for instances
26
- self.class_eval "def #{children_attr}
27
+ self.class_eval "def #{children_attr}(force_reload=false)
28
+ @#{children_attr} = false if force_reload
27
29
  @#{children_attr} ||= read_children(#{child_class})
28
30
  end"
29
31
  self.class_eval "def #{children_attr}=(value)
@@ -110,7 +112,7 @@ module OceanDynamo
110
112
  # Destroy all children not in the new set (this is not yet scalable)
111
113
  read_children(klass).each do |c|
112
114
  next if new_children.include?(c)
113
- c.delete
115
+ c.destroy
114
116
  end
115
117
  end
116
118
 
@@ -48,7 +48,15 @@ module OceanDynamo
48
48
 
49
49
  class UnknownAttributeError < NoMethodError; end
50
50
 
51
- class AttributeAssignmentError < DynamoError; end
51
+ class AttributeAssignmentError < DynamoError
52
+ attr_reader :exception, :attribute
53
+ def initialize(message, exception, attribute)
54
+ super(message)
55
+ @exception = exception
56
+ @attribute = attribute
57
+ end
58
+ end
59
+
52
60
 
53
61
  class MultiparameterAssignmentErrors < DynamoError; end
54
62
 
@@ -327,6 +327,7 @@ module OceanDynamo
327
327
  when :reference
328
328
  raise DynamoError, ":reference must always have a :target_class" unless target_class
329
329
  return value if value.is_a?(String)
330
+ # The next two lines should be superfluous now
330
331
  return value.id if value.kind_of?(target_class)
331
332
  raise AssociationTypeMismatch, "can't save a #{value.class} in a #{target_class} :reference"
332
333
  when :string
@@ -1,3 +1,3 @@
1
1
  module OceanDynamo
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ocean-dynamo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Bengtson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-25 00:00:00.000000000 Z
11
+ date: 2013-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -138,21 +138,21 @@ dependencies:
138
138
  version: 0.1.3
139
139
  description: "== OceanDynamo\n\nOceanDynamo is a massively scalable Amazon DynamoDB
140
140
  near drop-in replacement for \nActiveRecord.\n\nAs one important use case for OceanDynamo
141
- is to facilitate the conversion of SQL based\nActiveRecord models to DynamoDB based
142
- models, it is important that the syntax and semantics\nof OceanDynamo's operations
143
- are as close as possible to those of ActiveRecord, including\ncallbacks, exceptions
144
- and support methods. Ocean-dynamo follows this pattern closely and\nis of course
145
- based on ActiveModel.\n\nThe attribute and persistence layer of OceanDynamo is modeled
146
- on that of ActiveRecord:\nthere's +save+, +save!+, +create+, +update+, +update!+,
147
- +update_attributes+, +find_each+,\n+destroy_all+, +delete_all+ and all the other
148
- methods you're used to. The design goal \nis always to implement as much of the
149
- ActiveRecord interface as possible, without \ncompromising scalability. This makes
150
- the task of switching from SQL to no-SQL much easier.\n\nThanks to its structural
151
- similarity to ActiveRecord, OceanDynamo works with FactoryGirl.\nTo facilitate testing,
152
- future versions will keep track of and delete instances after tests.\n\nOceanDynamo
153
- uses primary indices to retrieve related table items, \nwhich means it will scale
154
- without limits.\n\nSee also Ocean, a Rails framework for creating highly scalable
155
- SOAs in the cloud, in which\nocean-dynamo is used as a central component: http://wiki.oceanframework.net"
141
+ is to facilitate the conversion of SQL\ndatabases to no-SQL DynamoDB databases,
142
+ it is important that the syntax and semantics\nof OceanDynamo are as close as possible
143
+ to those of ActiveRecord. This includes\ncallbacks, exceptions and method chaining
144
+ semantics. OceanDynamo follows this pattern \nclosely and is of course based on
145
+ ActiveModel.\n\nThe attribute and persistence layer of OceanDynamo is modeled on
146
+ that of ActiveRecord:\nthere's +save+, +save!+, +create+, +update+, +update!+, +update_attributes+,
147
+ +find_each+,\n+destroy_all+, +delete_all+ and all the other methods you're used
148
+ to. The design goal \nis always to implement as much of the ActiveRecord interface
149
+ as possible, without \ncompromising scalability. This makes the task of switching
150
+ from SQL to no-SQL much easier.\n\nThanks to its structural similarity to ActiveRecord,
151
+ OceanDynamo works with FactoryGirl.\nTo facilitate testing, future versions will
152
+ keep track of and delete instances after tests.\n\nOceanDynamo uses primary indices
153
+ to retrieve related table items, \nwhich means it will scale without limits.\n\nSee
154
+ also Ocean, a Rails framework for creating highly scalable SOAs in the cloud, in
155
+ which\nocean-dynamo is used as a central component: http://wiki.oceanframework.net"
156
156
  email:
157
157
  - peter@peterbengtson.com
158
158
  executables: []
@@ -160,9 +160,11 @@ extensions: []
160
160
  extra_rdoc_files: []
161
161
  files:
162
162
  - config/routes.rb
163
+ - lib/ocean-dynamo/active_record_stuff/collection_proxy.rb
164
+ - lib/ocean-dynamo/active_record_stuff/reflection.rb
165
+ - lib/ocean-dynamo/active_record_stuff/relation.rb
163
166
  - lib/ocean-dynamo/associations/associations.rb
164
167
  - lib/ocean-dynamo/associations/belongs_to.rb
165
- - lib/ocean-dynamo/associations/collection_proxy.rb
166
168
  - lib/ocean-dynamo/associations/has_many.rb
167
169
  - lib/ocean-dynamo/attributes.rb
168
170
  - lib/ocean-dynamo/basal.rb