Module: Neoid::Relationship

Defined in:
lib/neoid/relationship.rb

Defined Under Namespace

Modules: ClassMethods, InstanceMethods Classes: RelationshipLazyProxy

Class Method Summary collapse

Class Method Details

.from_hash(hash) ⇒ Object



15
16
17
18
19
# File 'lib/neoid/relationship.rb', line 15

def self.from_hash(hash)
  relationship = RelationshipLazyProxy.new(hash)

  relationship
end

.included(receiver) ⇒ Object



105
106
107
108
109
110
111
112
113
# File 'lib/neoid/relationship.rb', line 105

def self.included(receiver)
  receiver.send :include, Neoid::ModelAdditions
  receiver.send :include, InstanceMethods
  receiver.extend         ClassMethods
  
  initialize_relationship receiver if Neoid.env_loaded

  Neoid.relationship_models << receiver
end

.initialize_relationship(rel_model) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/neoid/relationship.rb', line 119

def self.initialize_relationship(rel_model)
  rel_model.reflect_on_all_associations(:belongs_to).each do |belongs_to|
    return if belongs_to.options[:polymorphic]

    # e.g. all has_many on User class
    all_has_many = belongs_to.klass.reflect_on_all_associations(:has_many)

    # has_many (without through) on the side of the relationship that removes a relationship. e.g. User has_many :likes
    this_has_many = all_has_many.find { |o| o.klass == rel_model }
    next unless this_has_many

    # e.g. User has_many :likes, after_remove: ...
    full_callback_name = "after_remove_for_#{this_has_many.name}"
    belongs_to.klass.send(full_callback_name) << :neo_after_relationship_remove if belongs_to.klass.method_defined?(full_callback_name)

    # has_many (with through) on the side of the relationship that removes a relationship. e.g. User has_many :movies, through :likes
    many_to_many = all_has_many.find { |o| o.options[:through] == this_has_many.name }
    next unless many_to_many

    return if many_to_many.options[:as] # polymorphic are not supported here yet

    # user_id
    foreign_key_of_owner = many_to_many.through_reflection.foreign_key

    # movie_id
    foreign_key_of_record = many_to_many.source_reflection.foreign_key

    (Neoid::Relationship. ||= {}).tap do |data|
      (data[belongs_to.klass.name.to_s] ||= {}).tap do |model_data|
        model_data[many_to_many.klass.name.to_s] = [rel_model.name.to_s, foreign_key_of_owner, foreign_key_of_record]
      end
    end

    # e.g. User has_many :movies, through: :likes, before_remove: ...
    full_callback_name = "before_remove_for_#{many_to_many.name}"
    belongs_to.klass.send(full_callback_name) << :neo_before_relationship_through_remove if belongs_to.klass.method_defined?(full_callback_name)


    # e.g. User has_many :movies, through: :likes, after_remove: ...
    full_callback_name = "after_remove_for_#{many_to_many.name}"
    belongs_to.klass.send(full_callback_name) << :neo_after_relationship_through_remove if belongs_to.klass.method_defined?(full_callback_name)
  end
end

.meta_dataObject



115
116
117
# File 'lib/neoid/relationship.rb', line 115

def self.
  @meta_data ||= {}
end