Class: Prim::Relationship

Inherits:
Object
  • Object
show all
Defined in:
lib/prim/relationship.rb

Overview

This class largely wraps ActiveRecord::Reflection::MacroReflection and its subclasses. A Relationship encapsulates the interaction among the two or three classes involved in a one-to-many or many-to-many model association, and reconfigures these classes to make handling primary members of those associations simple.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(association_name, owning_class, options = {}) ⇒ Relationship



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/prim/relationship.rb', line 11

def initialize association_name, owning_class, options = {}
  @options = options
  @association_name = association_name
  @owning_class = owning_class
  @reflection   = owning_class.reflect_on_association( association_name )

  # TODO: remove these exceptions and replace with logged errors? hmm.
  if reflection.nil?
    raise ArgumentError.new("Association '#{ association_name }' not found " +
      "on #{ owning_class.name }. Perhaps you misspelled it?")
  
  elsif !reflection.collection?
    raise SingularAssociationError.new("Association '#{ association_name }' " +
      "is not a one-to-many or many-to-many relationship, so it can't have a primary.")

  elsif !primary_column
    # TODO: add a generator to automatically create a migration, then change this
    # message to give users the exact instruction needed.
    raise InvalidPrimaryColumnError.new("#{ owning_class.name } needs table " +
      "`#{ mapping_reflection.table_name }` to have a boolean 'primary' column " +
      "in order to have a primary #{ source_class.name }.")
  end

  # TODO: ensure the association isn't nested?

  reflected_class.send :include, InstanceMethods::Reflected
  reflected_class.class_attribute :prim_relationship
  reflected_class.prim_relationship = self

  source_class.send :include, InstanceMethods::Source if mapping_table?
end

Instance Attribute Details

#association_nameObject (readonly)

Returns the value of attribute association_name.



8
9
10
# File 'lib/prim/relationship.rb', line 8

def association_name
  @association_name
end

#optionsObject (readonly)

Returns the value of attribute options.



8
9
10
# File 'lib/prim/relationship.rb', line 8

def options
  @options
end

#owning_classObject (readonly)

Returns the value of attribute owning_class.



8
9
10
# File 'lib/prim/relationship.rb', line 8

def owning_class
  @owning_class
end

#reflectionObject (readonly)

Returns the value of attribute reflection.



8
9
10
# File 'lib/prim/relationship.rb', line 8

def reflection
  @reflection
end

Instance Method Details

#collection_labelObject

The association method to call on the owning class to retrieve a record’s collection.



44
45
46
# File 'lib/prim/relationship.rb', line 44

def collection_label
  (options[:through] || mapping_reflection.plural_name).to_sym
end

#mapping_reflectionObject

The association reflection representing the link between the owning class and the mapping class, whether or not the mapping class represents a join-table.



60
61
62
# File 'lib/prim/relationship.rb', line 60

def mapping_reflection
  through_reflection || reflection
end

#mapping_table?Boolean

True if this relationship relies on a mapping table for ‘primary` records.



65
66
67
# File 'lib/prim/relationship.rb', line 65

def mapping_table?
  !!through_reflection
end

#reflected_classObject

The class of the ‘mapping_reflection`.



54
55
56
# File 'lib/prim/relationship.rb', line 54

def reflected_class
  mapping_reflection.klass
end

#source_classObject

The class of the reflection source: i.e. Post if the owning class ‘has_many :posts`.



49
50
51
# File 'lib/prim/relationship.rb', line 49

def source_class
  reflection.klass
end