Module: ActiveResource::Associations

Included in:
Base
Defined in:
lib/active_resource/associations.rb

Defined Under Namespace

Modules: Builder

Instance Method Summary collapse

Instance Method Details

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

Specifies a one-to-one association with another class. This class should only be used if this class contains the foreign key.

Methods will be added for retrieval and query for a single associated object, for which this object holds an id:

association(force_reload = false)

Returns the associated object. nil is returned if the foreign key is nil. Throws a ActiveResource::ResourceNotFound exception if the foreign key is not nil and the resource is not found.

(association is replaced with the symbol passed as the first argument, so belongs_to :post would add among others post.nil?.

Example

A Comment class declares belongs_to :post, which will add:

  • Comment#post (similar to Post.find(post_id))

The declaration can also include an options hash to specialize the behavior of the association.

Options

:class_name

Specify the class name for the association. Use it only if that name can’t be inferred from association name. So belongs_to :post will by default be linked to the Post class, but if the real class name is Article, you’ll have to specify it with this option.

:foreign_key

Specify the foreign key used for the association. By default this is guessed to be the name of the association with an “_id” suffix. So a class that defines a belongs_to :post association will use “post_id” as the default :foreign_key. Similarly, belongs_to :article, :class_name => "Post" will use a foreign key of “article_id”.

Option examples: belongs_to :customer, :class_name => 'User' Creates a belongs_to association called customer which is represented through the User class.

belongs_to :customer, :foreign_key => 'user_id' Creates a belongs_to association called customer which would be resolved by the foreign_key user_id instead of customer_id



116
117
118
# File 'lib/active_resource/associations.rb', line 116

def belongs_to(name, options = {})
  Builder::BelongsTo.build(self, name, options)
end

#defines_belongs_to_finder_method(reflection) ⇒ Object

Defines the belongs_to association finder method



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/active_resource/associations.rb', line 121

def defines_belongs_to_finder_method(reflection)
  method_name = reflection.name
  ivar_name = :"@#{method_name}"

  if method_defined?(method_name)
    instance_variable_set(ivar_name, nil)
    remove_method(method_name)
  end

  define_method(method_name) do
    if instance_variable_defined?(ivar_name)
      instance_variable_get(ivar_name)
    elsif attributes.include?(method_name)
      attributes[method_name]
    elsif association_id = send(reflection.foreign_key)
      instance_variable_set(ivar_name, reflection.klass.find(association_id))
    end
  end
end

#defines_has_many_finder_method(reflection) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/active_resource/associations.rb', line 141

def defines_has_many_finder_method(reflection)
  method_name = reflection.name
  ivar_name = :"@#{method_name}"

  define_method(method_name) do
    if instance_variable_defined?(ivar_name)
      instance_variable_get(ivar_name)
    elsif attributes.include?(method_name)
      attributes[method_name]
    elsif !new_record?
      instance_variable_set(ivar_name, reflection.klass.find(:all, params: { "#{self.class.element_name}_id": self.id }))
    else
      instance_variable_set(ivar_name, self.class.collection_parser.new)
    end
  end
end

#defines_has_one_finder_method(reflection) ⇒ Object

Defines the has_one association



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/active_resource/associations.rb', line 159

def defines_has_one_finder_method(reflection)
  method_name = reflection.name
  ivar_name = :"@#{method_name}"

  define_method(method_name) do
    if instance_variable_defined?(ivar_name)
      instance_variable_get(ivar_name)
    elsif attributes.include?(method_name)
      attributes[method_name]
    elsif reflection.klass.respond_to?(:singleton_name)
      instance_variable_set(ivar_name, reflection.klass.find(params: { "#{self.class.element_name}_id": self.id }))
    else
      instance_variable_set(ivar_name, reflection.klass.find(:one, from: "/#{self.class.collection_name}/#{self.id}/#{method_name}#{self.class.format_extension}"))
    end
  end
end

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

Specifies a one-to-many association.

Options

:class_name

Specify the class name of the association. This class name would be used for resolving the association class.

Example for [:class_name] - option

GET /posts/123.json delivers following response body:

{
  title: "ActiveResource now has associations",
  body: "Lorem Ipsum"
  comments: [
    {
      content: "..."
    },
    {
      content: "..."
    }
  ]
}

has_many :comments, :class_name => 'myblog/comment' Would resolve those comments into the Myblog::Comment class.

If the response body does not contain an attribute matching the association name a request sent to the index action under the current resource. For the example above, if the comments are not present the requested path would be: GET /posts/123/comments.xml



43
44
45
# File 'lib/active_resource/associations.rb', line 43

def has_many(name, options = {})
  Builder::HasMany.build(self, name, options)
end

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

Specifies a one-to-one association.

Options

:class_name

Specify the class name of the association. This class name would be used for resolving the association class.

Example for [:class_name] - option

GET /posts/1.json delivers following response body:

{
  title: "ActiveResource now has associations",
  body: "Lorem Ipsum",
  author: {
    name: "Gabby Blogger",
  }
}

has_one :author, :class_name => 'myblog/author' Would resolve this author into the Myblog::Author class.

If the response body does not contain an attribute matching the association name a request is sent to a singleton path under the current resource. For example, if a Product class has_one :inventory calling Product#inventory will generate a request on /products/:product_id/inventory.json.



73
74
75
# File 'lib/active_resource/associations.rb', line 73

def has_one(name, options = {})
  Builder::HasOne.build(self, name, options)
end