Module: ApiResource::Associations::ClassMethods

Defined in:
lib/api_resource/associations.rb

Instance Method Summary collapse

Instance Method Details

#association?(assoc) ⇒ Boolean

Returns:

  • (Boolean)


121
122
123
124
125
126
# File 'lib/api_resource/associations.rb', line 121

def association?(assoc)
  self.related_objects.any? do |key, value|
    next if key.to_s == "scopes"
    value.detect { |k,v| k.to_sym == assoc.to_sym }
  end
end

#association_class(assoc) ⇒ Object



133
134
135
# File 'lib/api_resource/associations.rb', line 133

def association_class(assoc)
  self.association_class_name(assoc).constantize
end

#association_class_name(assoc) ⇒ Object

Raises:

  • (ArgumentError)


137
138
139
140
141
142
143
# File 'lib/api_resource/associations.rb', line 137

def association_class_name(assoc)
  raise ArgumentError, "#{assoc} is not a valid association of #{self}" unless self.association?(assoc)
  result = self.related_objects.detect do |key,value|
    ret = value.detect{|k,v| k.to_sym == assoc.to_sym }
    return self.find_namespaced_class_name(ret[1]) if ret
  end
end

#association_foreign_key_field(assoc, type = nil) ⇒ Object

TODO: add a special foreign_key option to associations



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/api_resource/associations.rb', line 146

def association_foreign_key_field(assoc, type = nil)

  if type.nil? && has_many?(assoc)
    type = :has_many
  else
    type = type.to_s.to_sym
  end

  # for now just use the association name
  str = assoc.to_s.singularize.foreign_key

  if type.to_s =~ /^has_many/
    str = str.pluralize
  end

  str.to_sym
end

#association_namesObject



128
129
130
131
# File 'lib/api_resource/associations.rb', line 128

def association_names
  # structure is {:has_many => {"myname" => "ClassName"}}
  self.related_objects.clone.delete_if{|k,v| k.to_s == "scopes"}.collect{|k,v| v.keys.collect(&:to_sym)}.flatten
end

#define_association_methodsObject

Define the methods for creating and testing for associations, unfortunately scopes are different enough to require different methods :(



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/api_resource/associations.rb', line 77

def define_association_methods
  self.association_types.each_key do |assoc|
    self.instance_eval "      def \#{assoc}(*args)\n        options = args.extract_options!\n        options = options.with_indifferent_access\n        # Raise an error if we have multiple args and options\n        raise \"Invalid arguments to \#{assoc}\" unless options.blank? || args.length == 1\n        args.each do |arg|\n          klass_name = (options[:class_name] ? options[:class_name].to_s.classify : arg.to_s.classify)\n          # add this to any descendants - the other methods etc are handled by inheritance\n          ([self] + self.descendants).each do |klass|\n            #We need to merge upon itself to generate a new object since the children all share their related objects with each other\n            klass.related_objects = klass.related_objects.merge(:\#{assoc} => klass.related_objects[:\#{assoc}].merge(arg.to_sym => klass_name))\n          end\n          # We need to define reader and writer methods here\n          define_association_as_attribute(:\#{assoc}, arg, options)\n        end\n      end\n\n      def \#{assoc}?(name)\n        return self.related_objects[:\#{assoc}][name.to_s.pluralize.to_sym].present? || self.related_objects[:\#{assoc}][name.to_s.singularize.to_sym].present?\n      end\n\n      def \#{assoc}_class_name(name)\n        raise \"No such\" + :\#{assoc}.to_s + \" association on \#{name}\" unless self.\#{assoc}?(name)\n        return self.find_namespaced_class_name(self.related_objects[:\#{assoc}][name.to_sym])\n      end\n\n    EOE\n    # For convenience we will define the methods for testing for the existence of an association\n    # and getting the class for an association as instance methods too to avoid tons of self.class calls\n    self.class_eval <<-EOE, __FILE__, __LINE__ + 1\n      def \#{assoc}?(name)\n        return self.class.\#{assoc}?(name)\n      end\n\n      def \#{assoc}_class_name(name)\n        return self.class.\#{assoc}_class_name(name)\n      end\n    EOE\n  end\nend\n", __FILE__, __LINE__ + 1