Class: ROM::Changeset::Stateful Abstract

Inherits:
ROM::Changeset show all
Defined in:
lib/rom/repository/changeset/stateful.rb

Overview

This class is abstract.

Stateful changesets carry data and can transform it into a different structure compatible with a persistence backend

Direct Known Subclasses

Create, Update

Constant Summary collapse

EMPTY_PIPE =

Default no-op pipe

Pipe.new.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/rom/repository/changeset/stateful.rb', line 225

def method_missing(meth, *args, &block)
  if __data__.respond_to?(meth)
    response = __data__.__send__(meth, *args, &block)

    if response.is_a?(__data__.class)
      with(__data__: response)
    else
      response
    end
  else
    super
  end
end

Instance Attribute Details

#__data__Hash (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns The relation data.

Returns:

  • (Hash)

    The relation data



16
# File 'lib/rom/repository/changeset/stateful.rb', line 16

option :__data__, reader: true, optional: true, default: proc { nil }

#pipeChangeset::Pipe (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns data transformation pipe.

Returns:



21
22
23
# File 'lib/rom/repository/changeset/stateful.rb', line 21

option :pipe, reader: true, accept: [Proc, Pipe], default: -> changeset {
  changeset.class.default_pipe(changeset)
}

Class Method Details

.default_pipe(context) ⇒ Pipe

Build default pipe object

This can be overridden in a custom changeset subclass

Returns:



73
74
75
# File 'lib/rom/repository/changeset/stateful.rb', line 73

def self.default_pipe(context)
  pipes.size > 0 ? pipes.map { |p| p.bind(context) }.reduce(:>>) : EMPTY_PIPE
end

.inherited(klass) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



78
79
80
81
82
# File 'lib/rom/repository/changeset/stateful.rb', line 78

def self.inherited(klass)
  return if klass == ROM::Changeset
  super
  klass.instance_variable_set(:@__pipes__, pipes ? pipes.dup : EMPTY_ARRAY)
end

.map(&block) ⇒ Array<Pipe>, Transproc::Function

Define a changeset mapping

Subsequent mapping definitions will be composed together and applied in the order they way defined

Examples:

Transformation DSL

class NewUser < ROM::Changeset::Create
  map do
    unwrap :address, prefix: true
  end
end

Using custom block

class NewUser < ROM::Changeset::Create
  map do |tuple|
    tuple.merge(created_at: Time.now)
  end
end

Multiple mappings (executed in the order of definition)

class NewUser < ROM::Changeset::Create
  map do
    unwrap :address, prefix: true
  end

  map do |tuple|
    tuple.merge(created_at: Time.now)
  end
end

Returns:

  • (Array<Pipe>, Transproc::Function)

    ]

See Also:



60
61
62
63
64
65
66
# File 'lib/rom/repository/changeset/stateful.rb', line 60

def self.map(&block)
  if block.arity.zero?
    pipes << Class.new(Pipe, &block).new
  else
    pipes << Pipe.new(block)
  end
end

.pipesObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



85
86
87
# File 'lib/rom/repository/changeset/stateful.rb', line 85

def self.pipes
  @__pipes__
end

Instance Method Details

#associate(other, name) ⇒ Object

Associate a changeset with another changeset or hash-like object

Examples:

with another changeset

new_user = user_repo.changeset(name: 'Jane')
new_task = user_repo.changeset(:tasks, title: 'A task')

new_task.associate(new_user, :users)

with a hash-like object

user = user_repo.users.by_pk(1).one
new_task = user_repo.changeset(:tasks, title: 'A task')

new_task.associate(user, :users)

Parameters:

  • other (#to_hash, Changeset)

    Other changeset or hash-like object

  • assoc (Symbol)

    The association identifier from schema



190
191
192
# File 'lib/rom/repository/changeset/stateful.rb', line 190

def associate(other, name)
  Associated.new(self, other, association: name)
end

#commandObject



204
205
206
# File 'lib/rom/repository/changeset/stateful.rb', line 204

def command
  command_compiler.(command_type, relation_identifier, DEFAULT_COMMAND_OPTS.merge(result: result))
end

#commitObject

Commit stateful changeset



168
169
170
# File 'lib/rom/repository/changeset/stateful.rb', line 168

def commit
  command.call(self)
end

#data(data) ⇒ Changeset

Return changeset with data

Parameters:

  • data (Hash)

Returns:



135
136
137
# File 'lib/rom/repository/changeset/stateful.rb', line 135

def data(data)
  with(__data__: data)
end

#inspectString

Return string representation of the changeset

Returns:

  • (String)


213
214
215
# File 'lib/rom/repository/changeset/stateful.rb', line 213

def inspect
  %(#<#{self.class} relation=#{relation.name.inspect} data=#{__data__}>)
end

#map(*steps) ⇒ Changeset #map(&block) ⇒ Changeset #map(*steps, &block) ⇒ Changeset

Pipe changeset’s data using custom steps define on the pipe

Overloads:

  • #map(*steps) ⇒ Changeset

    Apply mapping using built-in transformations

    Examples:

    changeset.map(:add_timestamps)

    Parameters:

    • steps (Array<Symbol>)

      A list of mapping steps

  • #map(&block) ⇒ Changeset

    Apply mapping using a custom block

    Examples:

    changeset.map { |tuple| tuple.merge(created_at: Time.now) }
  • #map(*steps, &block) ⇒ Changeset

    Apply mapping using built-in transformations and a custom block

    Examples:

    changeset.map(:touch) { |tuple| tuple.merge(status: 'published') }

    Parameters:

    • steps (Array<Symbol>)

      A list of mapping steps

Returns:



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rom/repository/changeset/stateful.rb', line 116

def map(*steps, &block)
  if block
    if steps.size > 0
      map(*steps).map(&block)
    else
      with(pipe: pipe >> Pipe.new(block).bind(self))
    end
  else
    with(pipe: steps.reduce(pipe) { |a, e| a >> pipe[e] })
  end
end

#resultSymbol

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return command result type

Returns:

  • (Symbol)


199
200
201
# File 'lib/rom/repository/changeset/stateful.rb', line 199

def result
  __data__.is_a?(Array) ? :many : :one
end

#to_aArray Also known as: to_ary

Coerce changeset to an array

This will send the data through the pipe

Returns:

  • (Array)


158
159
160
# File 'lib/rom/repository/changeset/stateful.rb', line 158

def to_a
  result == :one ? [to_h] : __data__.map { |element| pipe.call(element) }
end

#to_hHash Also known as: to_hash

Coerce changeset to a hash

This will send the data through the pipe

Returns:

  • (Hash)


146
147
148
# File 'lib/rom/repository/changeset/stateful.rb', line 146

def to_h
  pipe.call(__data__)
end