Module: ActivePoro::Relations::ClassMethods

Defined in:
lib/active_poro/relations.rb

Instance Method Summary collapse

Instance Method Details

#belongs_to(target_name) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/active_poro/relations.rb', line 76

def belongs_to(target_name)
  # define getter method
  define_method target_name do
    instance_variable_get("@#{target_name}")
  end

  # define setter method
  define_method "#{target_name}=" do |member|
    previous_member = instance_variable_get("@#{target_name}")
    instance_variable_set("@#{target_name}", member)

    singular_reflection_name = self.class.name.underscore
    plural_reflection_name = singular_reflection_name.pluralize

    # add myself to reflected association
    if member.respond_to?(singular_reflection_name) && member.send(singular_reflection_name) != self
      member.send("#{singular_reflection_name}=", self)
    elsif member.respond_to? plural_reflection_name
      reflected_members = member.send(plural_reflection_name)
      member.send("#{plural_reflection_name}=", reflected_members + [self]) unless reflected_members.include? self
    else
      raise "Association definition missing: no #{singular_reflection_name} or #{plural_reflection_name} association defined in #{member.class}"
    end

    # remove myself from old reflected association
    if previous_member.respond_to? singular_reflection_name
        previous_member.send("#{singular_reflection_name}=", nil) if previous_member.send(singular_reflection_name) == self
    elsif previous_member.respond_to? plural_reflection_name
      previous_reflected_members = previous_member.send(plural_reflection_name)
      previous_member.send("#{plural_reflection_name}=", previous_reflected_members - [self]) if previous_reflected_members.include? self
    elsif previous_member.nil?
      # there wasn't any previous member
    else # there was a previous member
      raise "Ghost association definition: no #{singular_reflection_name} or #{plural_reflection_name} association defined in #{member.class}, although it was there previously, dirty contamination"
    end
  end
end

#has_many(target_name) ⇒ Object



6
7
8
9
10
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/active_poro/relations.rb', line 6

def has_many(target_name)

  # define getter method
  define_method target_name do
    instance_variable_get("@#{target_name}") || []
  end

  # define setter method
  define_method "#{target_name}=" do |members|

    # nil to empty
    members ||= []

    # set the instance variable only if I am now the rightful owner
    instance_variable_set("@#{target_name}", members)
    singular_reflection_name = self.class.name.underscore
    members.each do |member|

      current_owner = member.send(singular_reflection_name)
      if current_owner.nil? # no current assignment
        member.send "#{singular_reflection_name}=", self
      elsif current_owner != self # current assignment is not me
        other_members = current_owner.send target_name
        if other_members.include?(member)
          # take the element from the other member
          new_members = other_members - [member]
          current_owner.send "#{target_name}=", new_members
        else
          raise "Unmatching association; Current owner (#{current_owner.class.name}) of #{member.class.name} does not have it as a member"
        end
        # add me as associated to the member I am also including
        member.send "#{singular_reflection_name}=", self
      else
        # its already me, do not do anything
      end

    end
  end

  # the singular suffix for add and remove methods
  singular_target_name = target_name.to_s.singularize

  # define the "add_<name>" method
  define_method "add_#{singular_target_name}" do |member|
    send("#{target_name}=", (send(target_name) + [member]).uniq)
  end

  # define the "remove_<name>" method
  define_method "remove_#{singular_target_name}" do |member|
    send("#{target_name}=", (send(target_name) - [member]).uniq)
  end

end

#has_one(target_name) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/active_poro/relations.rb', line 60

def has_one(target_name)
  # define getter method
  define_method target_name do
    instance_variable_get("@#{target_name}")
  end

  # define setter method
  define_method "#{target_name}=" do |member|
    singular_reflection_name = self.class.name.underscore
    if member.respond_to?(singular_reflection_name) && member.send(singular_reflection_name) != self
      member.send "#{singular_reflection_name}=", self
    end
    instance_variable_set("@#{target_name}", member)
  end
end