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: :nullify) ⇒ 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. With :nullify, however, the hash key is set to the string “NULL” rather than binary NULL, as DynamoDB doesn’t permit storing empty fields.



26
27
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
# File 'lib/ocean-dynamo/associations/has_many.rb', line 26

def has_many(children, dependent: :nullify)            # :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