rom-repository 1.4.0 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -6
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +18 -1
- data/lib/rom-repository.rb +1 -2
- data/lib/rom/repository.rb +9 -216
- data/lib/rom/repository/class_interface.rb +16 -33
- data/lib/rom/repository/relation_reader.rb +46 -0
- data/lib/rom/repository/root.rb +3 -59
- data/lib/rom/repository/version.rb +1 -1
- metadata +9 -98
- data/.gitignore +0 -3
- data/.rspec +0 -3
- data/.travis.yml +0 -27
- data/.yardopts +0 -2
- data/Gemfile +0 -38
- data/Rakefile +0 -19
- data/lib/rom/open_struct.rb +0 -35
- data/lib/rom/repository/changeset.rb +0 -155
- data/lib/rom/repository/changeset/associated.rb +0 -100
- data/lib/rom/repository/changeset/create.rb +0 -16
- data/lib/rom/repository/changeset/delete.rb +0 -17
- data/lib/rom/repository/changeset/pipe.rb +0 -97
- data/lib/rom/repository/changeset/restricted.rb +0 -28
- data/lib/rom/repository/changeset/stateful.rb +0 -282
- data/lib/rom/repository/changeset/update.rb +0 -82
- data/lib/rom/repository/command_compiler.rb +0 -257
- data/lib/rom/repository/command_proxy.rb +0 -26
- data/lib/rom/repository/header_builder.rb +0 -65
- data/lib/rom/repository/mapper_builder.rb +0 -23
- data/lib/rom/repository/relation_proxy.rb +0 -337
- data/lib/rom/repository/relation_proxy/combine.rb +0 -320
- data/lib/rom/repository/relation_proxy/wrap.rb +0 -78
- data/lib/rom/repository/struct_builder.rb +0 -83
- data/lib/rom/struct.rb +0 -113
- data/log/.gitkeep +0 -0
- data/rom-repository.gemspec +0 -23
- data/spec/integration/changeset_spec.rb +0 -193
- data/spec/integration/command_macros_spec.rb +0 -191
- data/spec/integration/command_spec.rb +0 -228
- data/spec/integration/multi_adapter_spec.rb +0 -73
- data/spec/integration/repository/aggregate_spec.rb +0 -58
- data/spec/integration/repository_spec.rb +0 -406
- data/spec/integration/root_repository_spec.rb +0 -106
- data/spec/integration/typed_structs_spec.rb +0 -64
- data/spec/shared/database.rb +0 -79
- data/spec/shared/mappers.rb +0 -35
- data/spec/shared/models.rb +0 -41
- data/spec/shared/plugins.rb +0 -66
- data/spec/shared/relations.rb +0 -115
- data/spec/shared/repo.rb +0 -86
- data/spec/shared/seeds.rb +0 -30
- data/spec/shared/structs.rb +0 -140
- data/spec/spec_helper.rb +0 -83
- data/spec/support/mapper_registry.rb +0 -9
- data/spec/support/mutant.rb +0 -10
- data/spec/unit/changeset/associate_spec.rb +0 -120
- data/spec/unit/changeset/map_spec.rb +0 -111
- data/spec/unit/changeset_spec.rb +0 -186
- data/spec/unit/relation_proxy_spec.rb +0 -202
- data/spec/unit/repository/changeset_spec.rb +0 -197
- data/spec/unit/repository/inspect_spec.rb +0 -18
- data/spec/unit/repository/session_spec.rb +0 -251
- data/spec/unit/repository/transaction_spec.rb +0 -42
- data/spec/unit/session_spec.rb +0 -46
- data/spec/unit/struct_builder_spec.rb +0 -128
@@ -1,78 +0,0 @@
|
|
1
|
-
module ROM
|
2
|
-
class Repository
|
3
|
-
class RelationProxy
|
4
|
-
# Provides convenient methods for producing wrapped relations
|
5
|
-
#
|
6
|
-
# @api public
|
7
|
-
module Wrap
|
8
|
-
# Wrap other relations
|
9
|
-
#
|
10
|
-
# @example
|
11
|
-
# tasks.wrap(owner: [users, user_id: :id])
|
12
|
-
#
|
13
|
-
# @param [Hash] options
|
14
|
-
#
|
15
|
-
# @return [RelationProxy]
|
16
|
-
#
|
17
|
-
# @api public
|
18
|
-
def wrap(*names, **options)
|
19
|
-
new_wraps = wraps_from_names(names) + wraps_from_options(options)
|
20
|
-
|
21
|
-
relation = new_wraps.reduce(self) { |a, e|
|
22
|
-
name = e.meta[:wrap_from_assoc] ? e.meta[:combine_name] : e.base_name.relation
|
23
|
-
a.relation.for_wrap(e.meta.fetch(:keys), name)
|
24
|
-
}
|
25
|
-
|
26
|
-
__new__(relation, meta: { wraps: wraps + new_wraps })
|
27
|
-
end
|
28
|
-
|
29
|
-
# Shortcut to wrap parents
|
30
|
-
#
|
31
|
-
# @example
|
32
|
-
# tasks.wrap_parent(owner: users)
|
33
|
-
#
|
34
|
-
# @return [RelationProxy]
|
35
|
-
#
|
36
|
-
# @api public
|
37
|
-
def wrap_parent(options)
|
38
|
-
wrap(
|
39
|
-
options.each_with_object({}) { |(name, parent), h|
|
40
|
-
keys = combine_keys(parent, relation, :children)
|
41
|
-
h[name] = [parent, keys]
|
42
|
-
}
|
43
|
-
)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Return a wrapped representation of a loading-proxy relation
|
47
|
-
#
|
48
|
-
# This will carry meta info used to produce a correct AST from a relation
|
49
|
-
# so that correct mapper can be generated
|
50
|
-
#
|
51
|
-
# @return [RelationProxy]
|
52
|
-
#
|
53
|
-
# @api private
|
54
|
-
def wrapped(name, keys, wrap_from_assoc = false)
|
55
|
-
with(
|
56
|
-
name: name,
|
57
|
-
meta: {
|
58
|
-
keys: keys, wrap_from_assoc: wrap_from_assoc, wrap: true, combine_name: name
|
59
|
-
}
|
60
|
-
)
|
61
|
-
end
|
62
|
-
|
63
|
-
# @api private
|
64
|
-
def wraps_from_options(options)
|
65
|
-
options.map { |(name, (relation, keys))| relation.wrapped(name, keys) }
|
66
|
-
end
|
67
|
-
|
68
|
-
# @api private
|
69
|
-
def wraps_from_names(names)
|
70
|
-
names.map { |name|
|
71
|
-
assoc = associations[name]
|
72
|
-
registry[assoc.target.relation].wrapped(name, assoc.combine_keys(__registry__), true)
|
73
|
-
}
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
require 'dry/core/inflector'
|
2
|
-
require 'dry/core/cache'
|
3
|
-
require 'dry/core/class_builder'
|
4
|
-
|
5
|
-
require 'rom/struct'
|
6
|
-
require 'rom/open_struct'
|
7
|
-
require 'rom/schema/attribute'
|
8
|
-
|
9
|
-
module ROM
|
10
|
-
class Repository
|
11
|
-
# @api private
|
12
|
-
class StructBuilder
|
13
|
-
extend Dry::Core::Cache
|
14
|
-
|
15
|
-
def call(*args)
|
16
|
-
fetch_or_store(*args) do
|
17
|
-
name, header = args
|
18
|
-
attributes = visit(header).compact
|
19
|
-
|
20
|
-
if attributes.empty?
|
21
|
-
ROM::OpenStruct
|
22
|
-
else
|
23
|
-
build_class(name, ROM::Struct) do |klass|
|
24
|
-
attributes.each do |(name, type)|
|
25
|
-
klass.attribute(name, type)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
alias_method :[], :call
|
32
|
-
|
33
|
-
attr_reader :namespace
|
34
|
-
|
35
|
-
def initialize(namespace = nil)
|
36
|
-
@namespace = namespace || ROM::Struct
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def visit(ast)
|
42
|
-
name, node = ast
|
43
|
-
__send__("visit_#{name}", node)
|
44
|
-
end
|
45
|
-
|
46
|
-
def visit_header(node)
|
47
|
-
node.map(&method(:visit))
|
48
|
-
end
|
49
|
-
|
50
|
-
def visit_relation(node)
|
51
|
-
relation_name, meta, header = node
|
52
|
-
name = meta[:combine_name] || relation_name.relation
|
53
|
-
|
54
|
-
model = meta.fetch(:model) { call(name, header) }
|
55
|
-
|
56
|
-
member =
|
57
|
-
if model < Dry::Struct
|
58
|
-
model
|
59
|
-
else
|
60
|
-
Dry::Types::Definition.new(model).constructor(&model.method(:new))
|
61
|
-
end
|
62
|
-
|
63
|
-
if meta[:combine_type] == :many
|
64
|
-
[name, Types::Array.member(member)]
|
65
|
-
else
|
66
|
-
[name, member.optional]
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def visit_attribute(attr)
|
71
|
-
[attr.aliased? && !attr.wrapped? ? attr.alias : attr.name, attr.to_read_type]
|
72
|
-
end
|
73
|
-
|
74
|
-
def build_class(name, parent, &block)
|
75
|
-
Dry::Core::ClassBuilder.new(name: class_name(name), parent: parent, namespace: namespace).call(&block)
|
76
|
-
end
|
77
|
-
|
78
|
-
def class_name(name)
|
79
|
-
Dry::Core::Inflector.classify(Dry::Core::Inflector.singularize(name))
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
data/lib/rom/struct.rb
DELETED
@@ -1,113 +0,0 @@
|
|
1
|
-
require 'dry/struct'
|
2
|
-
|
3
|
-
module ROM
|
4
|
-
# Simple data-struct class
|
5
|
-
#
|
6
|
-
# ROM structs are plain data structures loaded by repositories.
|
7
|
-
# They implement Hash protocol which means that they can be used
|
8
|
-
# in places where Hash-like objects are supported.
|
9
|
-
#
|
10
|
-
# Repositories define subclasses of ROM::Struct automatically, they are
|
11
|
-
# defined in the ROM::Struct namespace by default, but you set it up
|
12
|
-
# to use your namespace/module as well.
|
13
|
-
#
|
14
|
-
# Structs are based on dry-struct gem, they include `schema` with detailed information
|
15
|
-
# about attribute types returned from relations, thus can be introspected to build
|
16
|
-
# additional functionality when desired.
|
17
|
-
#
|
18
|
-
# There is a caveat you should know about when working with structs. Struct classes
|
19
|
-
# have names but at the same time they're anonymous, i.e. you can't get the User struct class
|
20
|
-
# with ROM::Struct::User. ROM will create as many struct classes for User as needed,
|
21
|
-
# they all will have the same name and ROM::Struct::User will be the common parent class for
|
22
|
-
# them. Combined with the ability to provide your own namespace for structs this enables to
|
23
|
-
# pre-define the parent class.
|
24
|
-
#
|
25
|
-
# @example accessing relation struct model
|
26
|
-
# rom = ROM.container(:sql, 'sqlite::memory') do |conf|
|
27
|
-
# conf.default.create_table(:users) do
|
28
|
-
# primary_key :id
|
29
|
-
# column :name, String
|
30
|
-
# end
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# class UserRepo < ROM::Repository[:users]
|
34
|
-
# end
|
35
|
-
#
|
36
|
-
# user_repo = UserRepo.new(rom)
|
37
|
-
#
|
38
|
-
# # get auto-generated User struct
|
39
|
-
# model = user_repo.users.mapper.model
|
40
|
-
# # => ROM::Struct::User
|
41
|
-
#
|
42
|
-
# # see struct's schema attributes
|
43
|
-
#
|
44
|
-
# # model.schema[:id]
|
45
|
-
# # => #<Dry::Types::Constrained type=#<Dry::Types::Definition primitive=Integer options={}> options={:rule=>#<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#gt?> options={:args=>[0]}>, :meta=>{:primary_key=>true, :name=>:id, :source=>ROM::Relation::Name(users)}} rule=#<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#gt?> options={:args=>[0]}>>
|
46
|
-
#
|
47
|
-
# model.schema[:name]
|
48
|
-
# # => #<Dry::Types::Sum left=#<Dry::Types::Constrained type=#<Dry::Types::Definition primitive=NilClass options={}> options={:rule=>#<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#type?> options={:args=>[NilClass]}>} rule=#<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#type?> options={:args=>[NilClass]}>> right=#<Dry::Types::Definition primitive=String options={}> options={:meta=>{:name=>:name, :source=>ROM::Relation::Name(users)}}>
|
49
|
-
#
|
50
|
-
# @example passing a namespace with an existing parent class
|
51
|
-
# module Entities
|
52
|
-
# class User < ROM::Struct
|
53
|
-
# def upcased_name
|
54
|
-
# name.upcase
|
55
|
-
# end
|
56
|
-
# end
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
# class UserRepo < ROM::Repository[:users]
|
60
|
-
# struct_namespace Entities
|
61
|
-
# end
|
62
|
-
#
|
63
|
-
# user_repo = UserRepo.new(rom)
|
64
|
-
# user = user_repo.users.by_pk(1).one!
|
65
|
-
# user.name # => "Jane"
|
66
|
-
# user.upcased_name # => "JANE"
|
67
|
-
#
|
68
|
-
# @see http://dry-rb.org/gems/dry-struct dry-struct
|
69
|
-
# @see http://dry-rb.org/gems/dry-types dry-types
|
70
|
-
#
|
71
|
-
# @api public
|
72
|
-
class Struct < Dry::Struct
|
73
|
-
MissingAttribute = Class.new(NameError)
|
74
|
-
|
75
|
-
# Returns a short string representation
|
76
|
-
#
|
77
|
-
# @return [String]
|
78
|
-
#
|
79
|
-
# @api public
|
80
|
-
def to_s
|
81
|
-
"#<#{self.class}:0x#{(object_id << 1).to_s(16)}>"
|
82
|
-
end
|
83
|
-
|
84
|
-
# Return attribute value
|
85
|
-
#
|
86
|
-
# @param [Symbol] name The attribute name
|
87
|
-
#
|
88
|
-
# @api public
|
89
|
-
def fetch(name)
|
90
|
-
__send__(name)
|
91
|
-
end
|
92
|
-
|
93
|
-
if RUBY_VERSION < '2.3'
|
94
|
-
# @api private
|
95
|
-
def respond_to?(*)
|
96
|
-
super
|
97
|
-
end
|
98
|
-
else
|
99
|
-
# @api private
|
100
|
-
def respond_to_missing?(*)
|
101
|
-
super
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
def method_missing(method, *)
|
108
|
-
super
|
109
|
-
rescue NameError => error
|
110
|
-
raise MissingAttribute.new("#{ error.message } (not loaded attribute?)")
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
data/log/.gitkeep
DELETED
File without changes
|
data/rom-repository.gemspec
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require File.expand_path('../lib/rom/repository/version', __FILE__)
|
2
|
-
|
3
|
-
Gem::Specification.new do |gem|
|
4
|
-
gem.name = 'rom-repository'
|
5
|
-
gem.summary = 'Repository abstraction for rom-rb'
|
6
|
-
gem.description = 'rom-repository adds support for auto-mapping and commands on top of rom-rb relations'
|
7
|
-
gem.author = 'Piotr Solnica'
|
8
|
-
gem.email = 'piotr.solnica+oss@gmail.com'
|
9
|
-
gem.homepage = 'http://rom-rb.org'
|
10
|
-
gem.require_paths = ['lib']
|
11
|
-
gem.version = ROM::Repository::VERSION.dup
|
12
|
-
gem.files = `git ls-files`.split("\n").reject { |name| name.include?('benchmarks') || name.include?('examples') || name.include?('bin/console') }
|
13
|
-
gem.test_files = `git ls-files -- {spec}/*`.split("\n")
|
14
|
-
gem.license = 'MIT'
|
15
|
-
|
16
|
-
gem.add_runtime_dependency 'rom', '~> 3.3'
|
17
|
-
gem.add_runtime_dependency 'rom-mapper', '~> 0.5'
|
18
|
-
gem.add_runtime_dependency 'dry-core', '~> 0.3', '>= 0.3.1'
|
19
|
-
gem.add_runtime_dependency 'dry-struct', '~> 0.3'
|
20
|
-
|
21
|
-
gem.add_development_dependency 'rake', '~> 11.2'
|
22
|
-
gem.add_development_dependency 'rspec', '~> 3.5'
|
23
|
-
end
|
@@ -1,193 +0,0 @@
|
|
1
|
-
RSpec.describe 'Using changesets' do
|
2
|
-
include_context 'database'
|
3
|
-
include_context 'relations'
|
4
|
-
|
5
|
-
before do
|
6
|
-
module Test
|
7
|
-
class User < Dry::Struct
|
8
|
-
attribute :id, Dry::Types['strict.int']
|
9
|
-
attribute :name, Dry::Types['strict.string']
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
configuration.mappers do
|
14
|
-
define(:users) do
|
15
|
-
model Test::User
|
16
|
-
register_as :user
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe 'Create' do
|
22
|
-
subject(:repo) do
|
23
|
-
Class.new(ROM::Repository[:users]) {
|
24
|
-
relations :books, :posts
|
25
|
-
commands :create, update: :by_pk
|
26
|
-
}.new(rom)
|
27
|
-
end
|
28
|
-
|
29
|
-
let(:create_changeset) do
|
30
|
-
Class.new(ROM::Changeset::Create)
|
31
|
-
end
|
32
|
-
|
33
|
-
let(:add_book_changeset) do
|
34
|
-
Class.new(ROM::Changeset::Create[:books])
|
35
|
-
end
|
36
|
-
|
37
|
-
let(:update_changeset) do
|
38
|
-
Class.new(ROM::Changeset::Update)
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'can be passed to a command' do
|
42
|
-
changeset = repo.changeset(name: "Jane Doe")
|
43
|
-
command = repo.command(:create, repo.users)
|
44
|
-
result = command.(changeset)
|
45
|
-
|
46
|
-
expect(result.id).to_not be(nil)
|
47
|
-
expect(result.name).to eql("Jane Doe")
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'can be passed to a command graph' do
|
51
|
-
changeset = repo.changeset(
|
52
|
-
name: "Jane Doe", posts: [{ title: "Just Do It", alien: "or sutin" }]
|
53
|
-
)
|
54
|
-
|
55
|
-
command = repo.command(:create, repo.aggregate(:posts))
|
56
|
-
result = command.(changeset)
|
57
|
-
|
58
|
-
expect(result.id).to_not be(nil)
|
59
|
-
expect(result.name).to eql("Jane Doe")
|
60
|
-
expect(result.posts.size).to be(1)
|
61
|
-
expect(result.posts[0].title).to eql("Just Do It")
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'preprocesses data using changeset pipes' do
|
65
|
-
changeset = repo.changeset(:books, title: "rom-rb is awesome").map(:add_timestamps)
|
66
|
-
command = repo.command(:create, repo.books)
|
67
|
-
result = command.(changeset)
|
68
|
-
|
69
|
-
expect(result.id).to_not be(nil)
|
70
|
-
expect(result.title).to eql("rom-rb is awesome")
|
71
|
-
expect(result.created_at).to be_instance_of(Time)
|
72
|
-
expect(result.updated_at).to be_instance_of(Time)
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'preprocesses data using custom block' do
|
76
|
-
changeset = repo.
|
77
|
-
changeset(:books, title: "rom-rb is awesome").
|
78
|
-
map { |tuple| tuple.merge(created_at: Time.now) }
|
79
|
-
|
80
|
-
command = repo.command(:create, repo.books)
|
81
|
-
result = command.(changeset)
|
82
|
-
|
83
|
-
expect(result.id).to_not be(nil)
|
84
|
-
expect(result.title).to eql("rom-rb is awesome")
|
85
|
-
expect(result.created_at).to be_instance_of(Time)
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'preprocesses data using built-in steps and custom block' do
|
89
|
-
changeset = repo.
|
90
|
-
changeset(:books, title: "rom-rb is awesome").
|
91
|
-
extend(:touch) { |tuple| tuple.merge(created_at: Time.now) }
|
92
|
-
|
93
|
-
command = repo.command(:create, repo.books)
|
94
|
-
result = command.(changeset)
|
95
|
-
|
96
|
-
expect(result.id).to_not be(nil)
|
97
|
-
expect(result.title).to eql("rom-rb is awesome")
|
98
|
-
expect(result.created_at).to be_instance_of(Time)
|
99
|
-
expect(result.updated_at).to be_instance_of(Time)
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'preserves relation mappers with create' do
|
103
|
-
changeset = repo.
|
104
|
-
changeset(create_changeset).
|
105
|
-
new(repo.users.relation.as(:user)).
|
106
|
-
data(name: 'Joe Dane')
|
107
|
-
|
108
|
-
expect(changeset.commit).to eql(Test::User.new(id: 1, name: 'Joe Dane'))
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'creates changesets for non-root relations' do
|
112
|
-
repo.create(name: 'John Doe')
|
113
|
-
changeset = repo.changeset(add_book_changeset).data(title: 'The War of the Worlds')
|
114
|
-
|
115
|
-
expect(changeset.commit).
|
116
|
-
to include(
|
117
|
-
id: 1,
|
118
|
-
title: 'The War of the Worlds',
|
119
|
-
created_at: nil,
|
120
|
-
updated_at: nil
|
121
|
-
)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
describe 'Update' do
|
126
|
-
subject(:repo) do
|
127
|
-
Class.new(ROM::Repository[:books]) {
|
128
|
-
commands :create, update: :by_pk
|
129
|
-
}.new(rom)
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'can be passed to a command' do
|
133
|
-
book = repo.create(title: 'rom-rb is awesome')
|
134
|
-
|
135
|
-
changeset = repo
|
136
|
-
.changeset(book.id, title: 'rom-rb is awesome for real')
|
137
|
-
.extend(:touch)
|
138
|
-
|
139
|
-
expect(changeset.diff).to eql(title: 'rom-rb is awesome for real')
|
140
|
-
|
141
|
-
result = repo.update(book.id, changeset)
|
142
|
-
|
143
|
-
expect(result.id).to be(book.id)
|
144
|
-
expect(result.title).to eql('rom-rb is awesome for real')
|
145
|
-
expect(result.updated_at).to be_instance_of(Time)
|
146
|
-
end
|
147
|
-
|
148
|
-
it 'skips update execution with no diff' do
|
149
|
-
book = repo.create(title: 'rom-rb is awesome')
|
150
|
-
|
151
|
-
changeset = repo
|
152
|
-
.changeset(book.id, title: 'rom-rb is awesome')
|
153
|
-
.extend(:touch)
|
154
|
-
|
155
|
-
expect(changeset).to_not be_diff
|
156
|
-
|
157
|
-
result = repo.update(book.id, changeset)
|
158
|
-
|
159
|
-
expect(result.id).to be(book.id)
|
160
|
-
expect(result.title).to eql('rom-rb is awesome')
|
161
|
-
expect(result.updated_at).to be(nil)
|
162
|
-
end
|
163
|
-
|
164
|
-
it 'works with mixed several class-level pipes' do
|
165
|
-
book = repo.create(title: 'rom-rb is awesome')
|
166
|
-
|
167
|
-
changeset_class = Class.new(ROM::Changeset::Update[:books]) do
|
168
|
-
map { |title: | { title: title.upcase } }
|
169
|
-
extend { |title: | { title: title.reverse } }
|
170
|
-
end
|
171
|
-
|
172
|
-
changeset = repo
|
173
|
-
.changeset(changeset_class)
|
174
|
-
.by_pk(book.id)
|
175
|
-
.data(title: 'rom-rb is really awesome')
|
176
|
-
|
177
|
-
expect(changeset.diff).to eql(title: 'ROM-RB IS REALLY AWESOME')
|
178
|
-
expect(changeset.to_h).to eql(title: 'EMOSEWA YLLAER SI BR-MOR')
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'works with mixed several instance-level pipes' do
|
182
|
-
book = repo.create(title: 'rom-rb is awesome')
|
183
|
-
|
184
|
-
changeset = repo.
|
185
|
-
changeset(book.id, title: 'rom-rb is really awesome').
|
186
|
-
map { |title: | { title: title.upcase } }.
|
187
|
-
extend { |title: | { title: title.reverse } }
|
188
|
-
|
189
|
-
expect(changeset.diff).to eql(title: 'ROM-RB IS REALLY AWESOME')
|
190
|
-
expect(changeset.to_h).to eql(title: 'EMOSEWA YLLAER SI BR-MOR')
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|