Module: OceanDynamo::HasMany::ClassMethods

Defined in:
lib/ocean-dynamo/associations/has_many.rb

Overview


Class methods

Instance Method Summary collapse

Instance Method Details

#has_many(children, dependent: :delete) ⇒ Object

Defines a has_many relation to a belongs_to class.

The dependent: keyword arg may be :destroy, :delete or :nullify and have the same semantics as in ActiveRecord.

Using :nullify is a Bad Idea on DynamoDB, as it has to first read, then delete, and finally recreate each record. You should redesign your application to user either :delete (the default) or :destroy instead.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/ocean-dynamo/associations/has_many.rb', line 28

def has_many(children, dependent: :delete)             # :children
  children_attr = children.to_s.underscore             # "children"
  class_name = children_attr.classify                  # "Child"
  define_class_if_not_defined(class_name)
  child_class = class_name.constantize                 # Child
  register_relation(child_class, :has_many)

  # Handle children= after create and update
  after_save do |p|
    new_children = instance_variable_get("@#{children_attr}")  
    if new_children  # TODO: only do this for dirty collections
      write_children child_class, new_children
      map_children child_class do |c|
        next if new_children.include?(c)
        c.destroy
      end
    end 
    true
  end

  if dependent == :destroy
    before_destroy do |p|
      map_children(child_class, &:destroy)
      p.instance_variable_set "@#{children_attr}", nil
      true
    end

  elsif dependent == :delete
    before_destroy do |p|
      delete_children(child_class)
      p.instance_variable_set "@#{children_attr}", nil
   end

  elsif dependent == :nullify
    before_destroy do |p|
      nullify_children(child_class)
      p.instance_variable_set "@#{children_attr}", nil
      true
    end

  else
    raise ArgumentError, ":dependent must be :destroy, :delete, or :nullify"
  end

  # Define accessors for instances
  attr_accessor children_attr
  self.class_eval "def #{children_attr}(force_reload=false) 
                     @#{children_attr} = false if force_reload
                     @#{children_attr} ||= read_children(#{child_class})
                   end"
  self.class_eval "def #{children_attr}=(value)
                     @#{children_attr} = value
                   end"
  self.class_eval "def #{children_attr}? 
                     @#{children_attr} ||= read_children(#{child_class})
                     @#{children_attr}.present?
                   end"
end