Module: Hobo::Model::AccessibleAssociations

Extended by:
AccessibleAssociations
Included in:
AccessibleAssociations
Defined in:
lib/hobo/model/accessible_associations.rb

Instance Method Summary collapse

Instance Method Details

#find_by_name_or_id(finder, id_or_name) ⇒ Object



83
84
85
86
87
88
89
90
# File 'lib/hobo/model/accessible_associations.rb', line 83

def find_by_name_or_id(finder, id_or_name)
  if id_or_name =~ /^@(.*)/
    id = $1
    finder.find(id)
  else
    finder.named(id_or_name)
  end
end

#find_or_create_and_update(owner, association_name, finder, record_hash_or_string) ⇒ Object



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
59
60
61
62
63
64
# File 'lib/hobo/model/accessible_associations.rb', line 29

def find_or_create_and_update(owner, association_name, finder, record_hash_or_string)
  if record_hash_or_string.is_a?(String)
    return nil if record_hash_or_string.blank?

    # An ID or a name - the passed block will find the record
    record = find_by_name_or_id(finder, record_hash_or_string)

  elsif record_hash_or_string.is_a?(Hash)
    # A hash of attributes
    hash = record_hash_or_string

    # Remove completely blank hashes
    return nil if hash.values.all?(&:blank?)

    id = hash.delete(:id)

    record = yield id
    record.attributes = hash
    if owner.new_record? && record.new_record?
      # work around
      # https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/3510-has_many-build-does-not-set-reverse-reflection
      # https://hobo.lighthouseapp.com/projects/8324/tickets/447-validation-problems-with-has_many-accessible-true
      reverse = owner.class.reverse_reflection(association_name)
      if reverse && reverse.macro==:belongs_to
        method = "#{reverse.name}=".to_sym
        record.send(method, owner) if record.respond_to? method
      end
    else
      owner.include_in_save(association_name, record) unless owner.class.reflections[association_name.to_s].options[:through]
    end
  else
    # It's already a record
    record = record_hash_or_string
  end
  record
end

#finder_for_belongs_to(record, name) ⇒ Object



92
93
94
95
96
97
# File 'lib/hobo/model/accessible_associations.rb', line 92

def finder_for_belongs_to(record, name)
  refl = record.class.reflections[name.to_s]
  #conditions = ActiveRecord::Associations::BelongsToAssociation.new(record, refl).reflection.send(:conditions)
  conditions = [[]]
  conditions == [[]] || conditions == [[],[]] ? refl.klass : refl.klass.scoped(:conditions => conditions)
end

#params_hash_to_array(array_or_hash) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/hobo/model/accessible_associations.rb', line 67

def params_hash_to_array(array_or_hash)
  if array_or_hash.is_a?(Hash)
    array = array_or_hash.get(*array_or_hash.keys.sort_by(&:to_i))
  elsif array_or_hash.is_a?(String)
    # Due to the way that rails works, there's no good way to tell
    # the difference between an empty array and a params hash that
    # just isn't making any updates to the array.  So we're
    # hacking this in: if you pass an empty string where an array
    # is expected, we assume you wanted an empty array.
    array_or_hash.split(',')
  else
    array_or_hash
  end
end

#prepare_has_many_assignment(association, association_name, array_or_hash) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/hobo/model/accessible_associations.rb', line 7

def prepare_has_many_assignment(association, association_name, array_or_hash)
  owner = association.proxy_association.owner

  array = params_hash_to_array(array_or_hash)
  array.map! do |record_hash_or_string|
    finder = association.member_class
    conditions = association.proxy_association.reflection.options[:conditions]
    finder = finder.where(conditions) unless conditions == [[]] || conditions == [[],[]]
    find_or_create_and_update(owner, association_name, finder, record_hash_or_string) do |id|
      # The block is required to either locate find an existing record in the collection, or build a new one
      if id
        # TODO: We don't really want to find these one by one
        association.find(id)
      else
        association.build
      end
    end
  end
  array.compact
end