class ROM::Changeset::Associated

Associated changesets automatically set up FKs

@api public

Public Class Methods

infer_assoc_name(other) click to toggle source

Infer association name from an object with a schema

This expects other to be an object with a schema that includes a primary key attribute with :source meta information. This makes it work with both structs and relations

@see Stateful#associate

@api private

# File lib/rom/changeset/associated.rb, line 30
def self.infer_assoc_name(other)
  schema = other.class.schema
  attrs = schema.is_a?(Hash) ? schema.values : schema
  pk = attrs.detect { |attr| attr.meta[:primary_key] }

  if pk
    pk.meta[:source]
  else
    raise ArgumentError, "can't infer association name for #{other}"
  end
end

Public Instance Methods

associate(other, name = Associated.infer_assoc_name(other)) click to toggle source

Associate with other changesets

@see Changeset#associate

@return [Associated]

@api public

# File lib/rom/changeset/associated.rb, line 65
def associate(other, name = Associated.infer_assoc_name(other))
  self.class.new(left, associations: associations.merge(name => other))
end
command() click to toggle source

Create a composed command

@example using existing parent data

user_changeset = users.changeset(name: 'Jane')
task_changeset = tasks.changeset(title: 'Task One')

user = users.create(user_changeset)
task = tasks.create(task_changeset.associate(user, :user))

@example saving both parent and child in one go

user_changeset = users.changeset(name: 'Jane')
task_changeset = tasks.changeset(title: 'Task One')

task = tasks.create(task_changeset.associate(user, :user))

This works only with parent => child(ren) changeset hierarchy

@return [ROM::Command::Composite]

@api public

# File lib/rom/changeset/associated.rb, line 89
def command
  associations.reduce(left.command.curry(left)) do |a, (assoc, other)|
    case other
    when Changeset
      a >> other.command.with_association(assoc).curry(other)
    when Associated
      a >> other.command.with_association(assoc)
    when Array
      raise NotImplementedError, 'Changeset::Associate does not support arrays yet'
    else
      a.with_association(assoc, parent: other)
    end
  end
end
commit() click to toggle source

Commit changeset's composite command

@example

task_changeset = tasks.
  changeset(title: 'Task One').
  associate(user, :user).
  commit
# {:id => 1, :user_id => 1, title: 'Task One'}

@return [Array<Hash>, Hash]

@api public

# File lib/rom/changeset/associated.rb, line 54
def commit
  command.call
end
relation() click to toggle source

@api private

# File lib/rom/changeset/associated.rb, line 105
def relation
  left.relation
end