ocean-dynamo 0.4.1 → 0.4.2

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.
@@ -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