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

Returns a new instance of 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
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.

Returns:

  • (Boolean)


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