Module: RemoteAssociation::HasManyRemote

Included in:
Base::ClassMethods
Defined in:
lib/remote_association/has_many_remote.rb

Instance Method Summary collapse

Instance Method Details

#has_many_remote(remote_rel, options = {}) ⇒ Object

Specifies a one-to-many association with another class. This method should only be used if this class is a kind of ActiveResource::Base and service for this resource can return some kind of foreign key.

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

associations()

Returns the associated objects. [] is returned if none is found.

associations=(associates)

Just setter, no saves.

(associations is replaced with the symbol passed as the first argument, so has_many_remote :authors would add among others authors.nil?.)

Example

A Author class declares has_many_remote :profiles, which will add:

  • Author#profiles (similar to Profile.find(:all, params: { author_id: [author.id]}))

  • Author#profiles=(profile) (will set @profiles instance variable of Author# to profile value)

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

Options

:class_name

Specify the class name of the association. Use it only if that name can’t be inferred from the association name. So has_many_remote :profiles will by default be linked to the Profile class, but if the real class name is SocialProfile, you’ll have to specify it with this option.

:foreign_key

Specify the foreign key used for searching association on remote service. By default this is guessed to be the name of the current class with an “_id” suffix. So a class Author that defines a has_many_remote :profiles association will use “author_id” as the default :foreign_key. This key will be used in :get request. Example: GET http://example.com/profiles?author_id[]=1

Option examples:

has_many_remote :firms, :foreign_key => "client_of"
has_many_remote :badges, :class_name => "Label", :foreign_key => "author_id"


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
86
87
88
89
90
91
92
93
94
# File 'lib/remote_association/has_many_remote.rb', line 40

def has_many_remote(remote_rel, options ={})
  rel_options = {
      class_name: remote_rel.to_s.singularize.classify,
      foreign_key: self.model_name.to_s.foreign_key,
      association_type: :has_many_remote
  }.merge(options.symbolize_keys)

  add_activeresource_relation(remote_rel.to_sym, rel_options)

  class_eval <<-RUBY, __FILE__, __LINE__+1

    attr_accessor :#{remote_rel}

    ##
    # Adds a method to call remote relation
    #
    # === Example
    #
    #  def customers
    #    if remote_resources_loaded?
    #      @customers ? @customers : nil
    #    else
    #      join_key = self.class.primary_key
    #      @customers ||= Person.
    #        find(:all, params: self.class.build_params_hash_for_customers(self.send(join_key)))
    #    end
    #  end
    #
    def #{remote_rel}
      if remote_resources_loaded?
        @#{remote_rel} ? @#{remote_rel} : []
      else
        join_key = self.class.primary_key
        @#{remote_rel} ||= #{rel_options[:class_name]}.
          find(:all, params: self.class.build_params_hash_for_#{remote_rel}(self.send(join_key)))
      end
    end

    ##
    # Returns Hash with HTTP parameters to query remote API
    #
    # == Example
    #
    #  def self.build_params_hash_for_customer(keys)
    #    keys = [keys] unless keys.kind_of?(Array)
    #    {"user_id" => keys}
    #  end
    #
    def self.build_params_hash_for_#{remote_rel}(keys)
      keys = [keys] unless keys.kind_of?(Array)
      {"#{rel_options[:foreign_key]}" => keys}
    end

  RUBY
end