Module: AddressConcern::AddressAssociations::ClassMethods

Defined in:
lib/address_concern/address_associations.rb

Instance Method Summary collapse

Instance Method Details

#address_name_for_type(type) ⇒ Object



54
55
56
57
58
59
60
# File 'lib/address_concern/address_associations.rb', line 54

def address_name_for_type(type)
  if type
    :"#{type}_address"
  else
    :address
  end
end

#belongs_to_address(name = :address, inverse: nil, **options) ⇒ Object

Creates a belongs_to address association, named “address” by default but a different name may be provided. In the Address model, creates an inverse association unless you pass inverse: false.

You can pass options to the belongs_to, like this:

belongs_to_address :work_address, dependent: :destroy

You can also pass options to the inverse has_one assocation in the Address model, via the inverse option:

belongs_to_address :home_address, inverse: {foreign_key: :physical_address_id}


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
# File 'lib/address_concern/address_associations.rb', line 15

def belongs_to_address(name = :address, inverse: nil, **options)
  options.reverse_merge!({
    class_name: 'Address'
  })
  raise "association :#{name} already exists on #{self}" if reflect_on_association(name)
  belongs_to name, **options
  #puts %(reflect_on_association(#{name})=#{reflect_on_association(name).inspect})

  unless inverse == false
    inverse ||= {}
    inverse.reverse_merge!({
      name:        self.name.underscore.to_sym,
      inverse_of:  name,
      class_name:  self.name,
      foreign_key: "#{name}_id",
    })
    name       = inverse.delete(:name)
    inverse_of = inverse.delete(:inverse_of)
    Address.class_eval do
      raise "association :#{name} already exists on #{self}" if reflect_on_association(name)
      has_one name, inverse_of: inverse_of, **inverse
      #puts %(reflect_on_association(#{name})=#{reflect_on_association(name).inspect})
    end
  end
end

#create_addressable_association_on_address_if_needed(**options) ⇒ Object



76
77
78
79
80
81
# File 'lib/address_concern/address_associations.rb', line 76

def create_addressable_association_on_address_if_needed(**options)
  Address.class_eval do
    return if reflect_on_association(:addressable)
  end
  Address.belongs_to_addressable(**options)
end

#has_address(type = nil) ⇒ Object

Creates a has_one address association. If you don't give a name, it will just be called “address”, which can be used if this record only needs to be associated with a single address.

If you need it to be associated with multiple address records, pass the name/type of each. For example:

has_address :billing


49
50
51
52
# File 'lib/address_concern/address_associations.rb', line 49

def has_address(type = nil)
  has_one address_name_for_type(type), -> { where({address_type: type}) }, class_name: 'Address', as: :addressable
  create_addressable_association_on_address_if_needed
end

#has_addresses(types = []) ⇒ Object

Creates a has_many addresses association, representing all addresses associated with the current record

If types is given, adds a has_address(type) association for each type.

Comparable to acts_as_addressable from effective_addresses.



68
69
70
71
72
73
74
# File 'lib/address_concern/address_associations.rb', line 68

def has_addresses(types = [])
  has_many :addresses, as: :addressable
  (types || []).each do |type|
    has_address(type)
  end
  create_addressable_association_on_address_if_needed
end