Module: SimplyStored::Couch::HasMany

Included in:
ClassMethods
Defined in:
lib/simply_stored/couch/has_many.rb

Defined Under Namespace

Classes: Property

Instance Method Summary collapse

Instance Method Details

#define_has_many_count(name, options, through = nil) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/simply_stored/couch/has_many.rb', line 104

def define_has_many_count(name, options, through = nil)
  method_name = name.to_s.singularize.underscore + "_count"
  define_method(method_name) do |*args|
    local_options = args.first && args.first.is_a?(Hash) && args.first
    if local_options
      local_options.assert_valid_keys(:force_reload, :with_deleted)
      forced_reload = local_options[:force_reload]
      with_deleted = local_options[:with_deleted]
    else
      forced_reload = false
      with_deleted = false
    end

    if forced_reload || instance_variable_get("@#{method_name}").nil?
      instance_variable_set("@#{method_name}", count_associated(through || options[:class_name], self.class, :with_deleted => with_deleted, :foreign_key => options[:foreign_key]))
    end
    instance_variable_get("@#{method_name}")
  end
end

#define_has_many_getter(name, options) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/simply_stored/couch/has_many.rb', line 9

def define_has_many_getter(name, options)
  define_method(name) do |*args|
    local_options = args.first && args.first.is_a?(Hash) && args.first
    forced_reload, with_deleted, limit, descending = extract_association_options(local_options)

    cached_results = send("_get_cached_#{name}")
    cache_key = _cache_key_for(local_options)
    if forced_reload || cached_results[cache_key].nil? 
      cached_results[cache_key] = find_associated(options[:class_name], self.class, :with_deleted => with_deleted, :limit => limit, :descending => descending, :foreign_key => options[:foreign_key])
      instance_variable_set("@#{name}", cached_results)
      self.class.set_parent_has_many_association_object(self, cached_results[cache_key])
    end
    cached_results[cache_key]
  end
end

#define_has_many_setter_add(name, options) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/simply_stored/couch/has_many.rb', line 59

def define_has_many_setter_add(name, options)
  define_method("add_#{name.to_s.singularize}") do |value|
    klass = self.class.get_class_from_name(name)
    raise ArgumentError, "expected #{klass} got #{value.class}" unless value.is_a?(klass)
    
    value.send("#{self.class.foreign_key}=", id)
    value.save(false)
    
    cached_results = send("_get_cached_#{name}")[:all]
    send("_set_cached_#{name}", (cached_results || []) << value, :all)
    nil
  end
end

#define_has_many_setter_remove(name, options) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/simply_stored/couch/has_many.rb', line 73

def define_has_many_setter_remove(name, options)
  define_method "remove_#{name.to_s.singularize}" do |value|
    klass = self.class.get_class_from_name(name)
    raise ArgumentError, "expected #{klass} got #{value.class}" unless value.is_a?(klass)
    raise ArgumentError, "cannot remove not mine" unless value.send(self.class.foreign_key.to_sym) == id

    if options[:dependent] == :destroy
      value.destroy
    elsif options[:dependent] == :ignore
      # skip
    else # nullify
      value.send("#{self.class.foreign_key}=", nil)
      value.save(false)
    end
    
    cached_results = send("_get_cached_#{name}")[:all]
    send("_set_cached_#{name}", (cached_results || []).delete_if{|item| item.id == value.id}, :all)
    nil
  end
end

#define_has_many_setter_remove_all(name, options) ⇒ Object



94
95
96
97
98
99
100
101
102
# File 'lib/simply_stored/couch/has_many.rb', line 94

def define_has_many_setter_remove_all(name, options)
  define_method "remove_all_#{name}" do
    all = send("#{name}", :force_reload => true)
    
    all.collect{|i| i}.each do |item|
      send("remove_#{name.to_s.singularize}", item)
    end
  end
end

#define_has_many_through_getter(name, options, through) ⇒ Object

Raises:

  • (ArgumentError)


25
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
# File 'lib/simply_stored/couch/has_many.rb', line 25

def define_has_many_through_getter(name, options, through)
  raise ArgumentError, "no such relation: #{self} - #{through}" unless instance_methods.map(&:to_sym).include?(through.to_sym)
  
  define_method(name) do |*args|
    local_options = args.first && args.first.is_a?(Hash) && args.first
    if local_options
      local_options.assert_valid_keys(:force_reload, :with_deleted, :limit)
      forced_reload = local_options[:force_reload]
      with_deleted = local_options[:with_deleted]
      limit = local_options[:limit]
    else
      forced_reload = false
      with_deleted = false
      limit = nil
    end
    
    cached_results = send("_get_cached_#{name}")
    cache_key = _cache_key_for(local_options)
    
    if forced_reload || cached_results[cache_key].nil?
      
      # there is probably a faster way to query this
      intermediate_objects = find_associated(through, self.class, :with_deleted => with_deleted, :limit => limit, :foreign_key => options[:foreign_key])
      
      through_objects = intermediate_objects.map do |intermediate_object|
        intermediate_object.send(name.to_s.singularize.underscore, :with_deleted => with_deleted)
      end.flatten.uniq
      cached_results[cache_key] = through_objects
      instance_variable_set("@#{name}", cached_results)
    end
    cached_results[cache_key]
  end
end

#has_many(name, options = {}) ⇒ Object



4
5
6
7
# File 'lib/simply_stored/couch/has_many.rb', line 4

def has_many(name, options = {})
  check_existing_properties(name, SimplyStored::Couch::HasMany::Property)
  properties << SimplyStored::Couch::HasMany::Property.new(self, name, options)
end

#set_parent_has_many_association_object(parent, child_collection) ⇒ Object



124
125
126
127
128
129
130
# File 'lib/simply_stored/couch/has_many.rb', line 124

def set_parent_has_many_association_object(parent, child_collection)
  child_collection.each do |child|
    if child.respond_to?("#{parent.class.name.to_s.singularize.downcase}=")
      child.send("#{parent.class.name.to_s.singularize.camelize.downcase}=", parent)
    end
  end
end