class ActiveRecord::Base

the ever-useful to_label method

save and validation support for associations.

Public Instance Methods

associated_valid?(path = []) click to toggle source
# File lib/active_scaffold/extensions/unsaved_associated.rb, line 3
def associated_valid?(path = [])
  return true if path.include?(self) # prevent recursion (if associated and parent are new records)
  path << self
  # using [].all? syntax to avoid a short-circuit
  # errors to associated record can be added by update_record_from_params when association fails to set and ActiveRecord::RecordNotSaved is raised
  with_unsaved_associated { |a| [a.keeping_errors { a.valid? }, a.associated_valid?(path)].all? }
end
no_errors_in_associated?() click to toggle source
# File lib/active_scaffold/extensions/unsaved_associated.rb, line 19
def no_errors_in_associated?
  with_unsaved_associated { |a| a.errors.count.zero? && a.no_errors_in_associated? }
end
save_associated() click to toggle source
# File lib/active_scaffold/extensions/unsaved_associated.rb, line 11
def save_associated
  with_unsaved_associated { |a| a.save && a.save_associated }
end
save_associated!() click to toggle source
# File lib/active_scaffold/extensions/unsaved_associated.rb, line 15
def save_associated!
  save_associated || raise(ActiveRecord::RecordNotSaved, "Fail saving associations for #{inspect}")
end
to_label() click to toggle source
# File lib/active_scaffold/extensions/to_label.rb, line 3
def to_label
  to_label_method = ActiveScaffold::Registry.cache :to_label, self.class.name do
    %i[name label title to_s].find { |attribute| respond_to?(attribute) }
  end
  send(to_label_method).to_s if to_label_method
end

Protected Instance Methods

associations_for_update() click to toggle source

Provide an override to allow the model to restrict which associations are considered by ActiveScaffolds update mechanism. This allows the model to restrict things like Acts-As-Versioned versions associations being traversed.

By defining the method :scaffold_update_nofollow returning an array of associations these associations will not be traversed. By defining the method :scaffold_update_follow returning an array of associations, only those associations will be traversed.

Otherwise the default behaviour of traversing all associations will be preserved.

# File lib/active_scaffold/extensions/unsaved_associated.rb, line 35
def associations_for_update
  if respond_to?(:scaffold_update_nofollow)
    self.class.reflect_on_all_associations.reject { |association| scaffold_update_nofollow.include?(association.name) }
  elsif respond_to?(:scaffold_update_follow)
    self.class.reflect_on_all_associations.select { |association| scaffold_update_follow.include?(association.name) }
  else
    self.class.reflect_on_all_associations
  end
end

Private Instance Methods

with_unsaved_associated() { |r| ... } click to toggle source

yields every associated object that has been instantiated and is flagged as unsaved. returns false if any yield returns false. returns true otherwise, even when none of the associations have been instantiated. build wrapper methods accordingly.

# File lib/active_scaffold/extensions/unsaved_associated.rb, line 50
def with_unsaved_associated
  associations_for_update.map do |assoc|
    association_proxy = association(assoc.name)
    if association_proxy.target.present?
      records = association_proxy.target
      records = [records] unless records.is_a? Array # convert singular associations into collections for ease of use
      # must use select instead of find_all, which Rails overrides on association proxies for db access
      records.select { |r| r.unsaved? && !r.readonly? }.map { |r| yield r }.all?
    else
      true
    end
  end.all?
end