require "her/model/associations/association" require "her/model/associations/belongs_to_association" require "her/model/associations/has_many_association" require "her/model/associations/has_one_association" module Her module Model # This module adds associations to models module Associations extend ActiveSupport::Concern # Returns true if the model has a association_name association, false otherwise. def has_association?(association_name) associations = self.class.associations.values.flatten.map { |r| r[:name] } associations.include?(association_name) end alias :has_relationship? :has_association? # Returns the resource/collection corresponding to the association_name association. def get_association(association_name) send(association_name) if has_association?(association_name) end alias :get_relationship :get_association module ClassMethods # Return @_her_associations, lazily initialized with copy of the # superclass' her_associations, or an empty hash. # # @private def associations @_her_associations ||= begin superclass.respond_to?(:associations) ? superclass.associations.dup : Hash.new { |h,k| h[k] = [] } end end alias :relationships :associations # Parse associations data after initializing a new object # # @private def parse_associations(data) associations.each_pair do |type, definitions| definitions.each do |association| data_key = association[:data_key] next unless data[data_key] klass = self.her_nearby_class(association[:class_name]) name = association[:name] data[name] = case type when :has_many Her::Model::Attributes.initialize_collection(klass, :data => data[data_key]) when :has_one, :belongs_to klass.new(data[data_key]) else nil end end end data end # Define an *has_many* association. # # @param [Symbol] name The name of the model # @param [Hash] attrs Options (currently not used) # # @example # class User # include Her::Model # has_many :articles # end # # class Article # include Her::Model # end # # @user = User.find(1) # @user.articles # => [#<Article(articles/2) id=2 title="Hello world.">] # # Fetched via GET "/users/1/articles" def has_many(name, attrs={}) Her::Model::Associations::HasManyAssociation.attach(self, name, attrs) end # Define an *has_one* association. # # @param [Symbol] name The name of the model # @param [Hash] attrs Options # # @example # class User # include Her::Model # has_one :organization # end # # class Organization # include Her::Model # end # # @user = User.find(1) # @user.organization # => #<Organization(organizations/2) id=2 name="Foobar Inc."> # # Fetched via GET "/users/1/organization" def has_one(name, attrs={}) Her::Model::Associations::HasOneAssociation.attach(self, name, attrs) end # Define a *belongs_to* association. # # @param [Symbol] name The name of the model # @param [Hash] attrs Options # # @example # class User # include Her::Model # belongs_to :team, :class_name => "Group" # end # # class Group # include Her::Model # end # # @user = User.find(1) # => #<User(users/1) id=1 team_id=2 name="Tobias"> # @user.team # => #<Team(teams/2) id=2 name="Developers"> # # Fetched via GET "/teams/2" def belongs_to(name, attrs={}) Her::Model::Associations::BelongsToAssociation.attach(self, name, attrs) end end end end end