module AcceptsNestedIds::ClassMethods

Public Instance Methods

accepts_nested_ids_for(*args) click to toggle source

Sets up defered save and dirty tracking for the specified associations

@example When class_name can be inferred from association name

include AcceptsNestedIds
accepts_nested_ids_for :documents, :users

@example When class_name is different from association name

include AcceptsNestedIds
accepts_nested_ids_for :documents, included_users: "User"

@param args [Array]

# File lib/accepts_nested_ids.rb, line 50
def accepts_nested_ids_for(*args)
  @_nested_id_associations = map_nested_id_associations(*args)

  nested_id_associations.each do |nested_id_association|

    # Define ids_attr getter
    #
    # @example Method definition
    #   def document_ids
    #     @document_ids || (documents.loaded? ? documents.map(&:id) : documents.pluck(:id))
    #   end
    #
    define_method("#{nested_id_association.ids_attr}") do
      association = send(nested_id_association.attr)
      instance_variable_get("@#{nested_id_association.ids_attr}") ||
        (association.loaded? ? association.map(&:id) : association.pluck(:id))
    end

    # Define ids_attr setter
    #
    # @example Method definition
    #   def document_ids=(value)
    #     return if document_ids == value
    #     attribute_will_change!('document_ids')
    #     @document_ids = value
    #   end
    #
    define_method("#{nested_id_association.ids_attr}=") do |value|
      return if send(nested_id_association.ids_attr) == value
      attribute_will_change!(nested_id_association.ids_attr)
      instance_variable_set(:"@#{nested_id_association.ids_attr}", value)
    end

  end
end
nested_id_associations() click to toggle source
# File lib/accepts_nested_ids.rb, line 86
def nested_id_associations
  @_nested_id_associations || []
end

Private Instance Methods

get_ids_attr(attr) click to toggle source

@example

get_ids_attr(:documents) => "document_ids"

@param attr [Symbol] Association attribute name @return [String]

# File lib/accepts_nested_ids.rb, line 125
def get_ids_attr(attr)
  "#{attr.to_s.singularize}_ids"
end
map_nested_id_associations(*args) click to toggle source

Map module args into array of NestedIdAssociation objects with supporting properties

@example

accepts_nested_ids_for :documents, included_users: "User"
=>
[
  { attr: :documents:, ids_attr: "document_ids", class_name: "Document"},
  { attr: :included_users, ids_attr: "included_user_ids", class_name: "User" }
]

@param args [Array] @return [Array]

# File lib/accepts_nested_ids.rb, line 104
def map_nested_id_associations(*args)
  args.inject([]) do |array, arg|
    if arg.is_a?(Hash)
      attr        = arg.keys.first
      ids_attr    = get_ids_attr(attr)
      class_name  = arg[attr]
    else
      attr        = arg
      ids_attr    = get_ids_attr(attr)
      class_name  = arg.to_s.classify
    end
    array << NestedIdAssociation.new(attr, ids_attr, class_name)
    array
  end
end