rom-repository 1.4.0 → 2.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -6
  3. data/{LICENSE.txt → LICENSE} +1 -1
  4. data/README.md +18 -1
  5. data/lib/rom-repository.rb +1 -2
  6. data/lib/rom/repository.rb +9 -216
  7. data/lib/rom/repository/class_interface.rb +16 -33
  8. data/lib/rom/repository/relation_reader.rb +46 -0
  9. data/lib/rom/repository/root.rb +3 -59
  10. data/lib/rom/repository/version.rb +1 -1
  11. metadata +9 -98
  12. data/.gitignore +0 -3
  13. data/.rspec +0 -3
  14. data/.travis.yml +0 -27
  15. data/.yardopts +0 -2
  16. data/Gemfile +0 -38
  17. data/Rakefile +0 -19
  18. data/lib/rom/open_struct.rb +0 -35
  19. data/lib/rom/repository/changeset.rb +0 -155
  20. data/lib/rom/repository/changeset/associated.rb +0 -100
  21. data/lib/rom/repository/changeset/create.rb +0 -16
  22. data/lib/rom/repository/changeset/delete.rb +0 -17
  23. data/lib/rom/repository/changeset/pipe.rb +0 -97
  24. data/lib/rom/repository/changeset/restricted.rb +0 -28
  25. data/lib/rom/repository/changeset/stateful.rb +0 -282
  26. data/lib/rom/repository/changeset/update.rb +0 -82
  27. data/lib/rom/repository/command_compiler.rb +0 -257
  28. data/lib/rom/repository/command_proxy.rb +0 -26
  29. data/lib/rom/repository/header_builder.rb +0 -65
  30. data/lib/rom/repository/mapper_builder.rb +0 -23
  31. data/lib/rom/repository/relation_proxy.rb +0 -337
  32. data/lib/rom/repository/relation_proxy/combine.rb +0 -320
  33. data/lib/rom/repository/relation_proxy/wrap.rb +0 -78
  34. data/lib/rom/repository/struct_builder.rb +0 -83
  35. data/lib/rom/struct.rb +0 -113
  36. data/log/.gitkeep +0 -0
  37. data/rom-repository.gemspec +0 -23
  38. data/spec/integration/changeset_spec.rb +0 -193
  39. data/spec/integration/command_macros_spec.rb +0 -191
  40. data/spec/integration/command_spec.rb +0 -228
  41. data/spec/integration/multi_adapter_spec.rb +0 -73
  42. data/spec/integration/repository/aggregate_spec.rb +0 -58
  43. data/spec/integration/repository_spec.rb +0 -406
  44. data/spec/integration/root_repository_spec.rb +0 -106
  45. data/spec/integration/typed_structs_spec.rb +0 -64
  46. data/spec/shared/database.rb +0 -79
  47. data/spec/shared/mappers.rb +0 -35
  48. data/spec/shared/models.rb +0 -41
  49. data/spec/shared/plugins.rb +0 -66
  50. data/spec/shared/relations.rb +0 -115
  51. data/spec/shared/repo.rb +0 -86
  52. data/spec/shared/seeds.rb +0 -30
  53. data/spec/shared/structs.rb +0 -140
  54. data/spec/spec_helper.rb +0 -83
  55. data/spec/support/mapper_registry.rb +0 -9
  56. data/spec/support/mutant.rb +0 -10
  57. data/spec/unit/changeset/associate_spec.rb +0 -120
  58. data/spec/unit/changeset/map_spec.rb +0 -111
  59. data/spec/unit/changeset_spec.rb +0 -186
  60. data/spec/unit/relation_proxy_spec.rb +0 -202
  61. data/spec/unit/repository/changeset_spec.rb +0 -197
  62. data/spec/unit/repository/inspect_spec.rb +0 -18
  63. data/spec/unit/repository/session_spec.rb +0 -251
  64. data/spec/unit/repository/transaction_spec.rb +0 -42
  65. data/spec/unit/session_spec.rb +0 -46
  66. data/spec/unit/struct_builder_spec.rb +0 -128
@@ -1,106 +0,0 @@
1
- RSpec.describe ROM::Repository::Root do
2
- subject(:repo) do
3
- Class.new(ROM::Repository[:users]) do
4
- relations :tasks, :posts, :labels
5
- end.new(rom)
6
- end
7
-
8
- include_context 'database'
9
- include_context 'relations'
10
-
11
- describe '.[]' do
12
- it 'creates a pre-configured root repo class' do
13
- klass = ROM::Repository[:users]
14
-
15
- expect(klass.relations).to eql([:users])
16
- expect(klass.root).to be(:users)
17
-
18
- child = klass[:users]
19
-
20
- expect(child.relations).to eql([:users])
21
- expect(child.root).to be(:users)
22
- expect(child < klass).to be(true)
23
- end
24
- end
25
-
26
- describe 'inheritance' do
27
- it 'inherits root and relations' do
28
- klass = Class.new(repo.class)
29
-
30
- expect(klass.relations).to eql([:users, :tasks, :posts, :labels])
31
- expect(klass.root).to be(:users)
32
- end
33
-
34
- it 'creates base root class' do
35
- klass = Class.new(ROM::Repository)[:users]
36
-
37
- expect(klass.relations).to eql([:users])
38
- expect(klass.root).to be(:users)
39
- end
40
- end
41
-
42
- describe '#root' do
43
- it 'returns configured root relation' do
44
- expect(repo.root.relation).to be(rom.relations[:users])
45
- end
46
- end
47
-
48
- describe '#changeset' do
49
- it 'returns a changeset automatically set for root relation' do
50
- klass = Class.new(ROM::Changeset::Create)
51
-
52
- changeset = repo.changeset(klass)
53
-
54
- expect(changeset.relation).to be(repo.users)
55
- expect(changeset).to be_kind_of(klass)
56
- end
57
- end
58
-
59
- describe '#aggregate' do
60
- include_context 'seeds'
61
-
62
- it 'builds an aggregate from the root relation and other relation(s)' do
63
- user = repo.aggregate(many: repo.tasks).where(name: 'Jane').one
64
-
65
- expect(user.name).to eql('Jane')
66
- expect(user.tasks.size).to be(1)
67
- expect(user.tasks[0].title).to eql('Jane Task')
68
- end
69
-
70
- context 'with associations' do
71
- it 'builds an aggregate from a canonical association' do
72
- user = repo.aggregate(:labels).where(name: 'Joe').one
73
-
74
- expect(user.name).to eql('Joe')
75
- expect(user.labels.size).to be(1)
76
- expect(user.labels[0].name).to eql('green')
77
- end
78
-
79
- it 'builds an aggregate with nesting level = 2' do
80
- user = repo.aggregate(posts: [:labels, :author]).where(name: 'Joe').one
81
-
82
- expect(user.name).to eql('Joe')
83
- expect(user.posts.size).to be(1)
84
- expect(user.posts[0].title).to eql('Hello From Joe')
85
- expect(user.posts[0].labels.size).to be(1)
86
- end
87
-
88
- it 'builds a command from an aggregate' do
89
- command = repo.command(:create, repo.aggregate(:posts))
90
-
91
- result = command.call(name: 'Jade', posts: [{ title: 'Jade post' }])
92
-
93
- expect(result.name).to eql('Jade')
94
- expect(result.posts.size).to be(1)
95
- expect(result.posts[0].title).to eql('Jade post')
96
- end
97
-
98
- it 'builds same relation as manual combine' do
99
- left = repo.aggregate(:posts)
100
- right = repo.users.combine_children(many: repo.posts)
101
-
102
- expect(left.to_ast).to eql(right.to_ast)
103
- end
104
- end
105
- end
106
- end
@@ -1,64 +0,0 @@
1
- RSpec.describe 'ROM repository with typed structs' do
2
- subject(:repo) do
3
- Class.new(ROM::Repository[:books]) { commands :create }.new(rom)
4
- end
5
-
6
- include_context 'database'
7
- include_context 'seeds'
8
-
9
- context 'typed projections' do
10
- before do
11
- configuration.relation(:books) do
12
- schema(infer: true)
13
-
14
- view(:index) do
15
- schema { project(:id, :title, :created_at) }
16
- relation { order(:title) }
17
- end
18
- end
19
-
20
- rom.relations[:books].insert(title: 'Hello World', created_at: Time.now)
21
- end
22
-
23
- it 'loads typed structs' do
24
- book = repo.books.index.first
25
-
26
- expect(book).to be_kind_of(Dry::Struct)
27
-
28
- expect(book.id).to be_kind_of(Integer)
29
- expect(book.title).to eql('Hello World')
30
- expect(book.created_at).to be_kind_of(Time)
31
- end
32
- end
33
-
34
- context 'read-write type coercions' do
35
- before do
36
- configuration.relation(:books) do
37
- schema(infer: true) do
38
- attribute :title,
39
- ROM::Types::Coercible::String.meta(
40
- read: ROM::Types::Symbol.constructor(&:to_sym)
41
- )
42
- end
43
- end
44
-
45
- configuration.commands(:books) do
46
- define(:create) { result(:one) }
47
- end
48
- end
49
-
50
- it 'loads typed structs' do
51
- created_book = repo.create(title: :'Hello World', created_at: Time.now)
52
-
53
- expect(created_book).to be_kind_of(Dry::Struct)
54
-
55
- expect(created_book.id).to be_kind_of(Integer)
56
- expect(created_book.title).to eql(:'Hello World')
57
- expect(created_book.created_at).to be_kind_of(Time)
58
-
59
- book = repo.books.to_a.first
60
-
61
- expect(book).to eql(created_book)
62
- end
63
- end
64
- end
@@ -1,79 +0,0 @@
1
- RSpec.shared_context 'database setup' do
2
- let(:configuration) { ROM::Configuration.new(:sql, DB_URI) }
3
-
4
- let(:conn) { configuration.gateways[:default].connection }
5
-
6
- let(:rom) { ROM.container(configuration) }
7
-
8
- before do
9
- conn.loggers << LOGGER
10
- end
11
- end
12
-
13
- RSpec.shared_context 'database' do
14
- include_context 'database setup'
15
-
16
- before do
17
- [:tags, :tasks, :posts, :books, :users, :posts_labels, :labels,
18
- :reactions, :messages].each { |table| conn.drop_table?(table) }
19
-
20
- conn.create_table :users do
21
- primary_key :id
22
- column :name, String
23
- end
24
-
25
- conn.create_table :books do
26
- primary_key :id
27
- foreign_key :author_id, :users, on_delete: :cascade
28
- column :title, String
29
- column :created_at, Time
30
- column :updated_at, Time
31
- end
32
-
33
- conn.create_table :tasks do
34
- primary_key :id
35
- foreign_key :user_id, :users, null: false, on_delete: :cascade
36
- column :title, String
37
- end
38
-
39
- conn.create_table :tags do
40
- primary_key :id
41
- foreign_key :task_id, :tasks, null: false, on_delete: :cascade
42
- column :name, String
43
- end
44
-
45
- conn.create_table :labels do
46
- primary_key :id
47
- column :name, String
48
- end
49
-
50
- conn.create_table :posts do
51
- primary_key :id
52
- foreign_key :author_id, :users, null: false, on_delete: :cascade
53
- column :title, String, null: false
54
- column :body, String
55
- end
56
-
57
- conn.create_table :posts_labels do
58
- foreign_key :post_id, :labels, null: false, on_delete: :cascade
59
- foreign_key :label_id, :labels, null: false, on_delete: :cascade
60
- primary_key [:post_id, :label_id]
61
- end
62
-
63
- conn.create_table :messages do
64
- primary_key :message_id
65
- column :author, String
66
- column :body, String
67
- end
68
-
69
- conn.create_table :reactions do
70
- primary_key :reaction_id
71
- foreign_key :message_id, :messages, null: false
72
- column :author, String
73
- end
74
- end
75
-
76
- after do
77
- rom.disconnect
78
- end
79
- end
@@ -1,35 +0,0 @@
1
- RSpec.shared_context 'mappers' do
2
- let(:user_mappers) { users.mappers[:user] }
3
- let(:task_mappers) { tasks.mappers[:task] }
4
- let(:tag_mappers) { tags.mappers[:tag] }
5
-
6
- before do
7
- configuration.mappers do
8
- define(:users) do
9
- model Test::Models::User
10
- register_as :user
11
-
12
- attribute :id
13
- attribute :name
14
- end
15
-
16
- define(:tasks) do
17
- model Test::Models::Task
18
- register_as :task
19
-
20
- attribute :id
21
- attribute :user_id
22
- attribute :title
23
- end
24
-
25
- define(:tags) do
26
- model Test::Models::Tag
27
- register_as :tag
28
-
29
- attribute :id
30
- attribute :task_id
31
- attribute :name
32
- end
33
- end
34
- end
35
- end
@@ -1,41 +0,0 @@
1
- RSpec.shared_context 'models' do
2
- let(:user_model) { Test::Models::User }
3
- let(:task_model) { Test::Models::Task }
4
- let(:tag_model) { Test::Models::Tag }
5
-
6
- before do
7
- module Test
8
- module Models
9
- class User
10
- include Dry::Equalizer(:id, :name)
11
-
12
- attr_reader :id, :name
13
-
14
- def initialize(attrs)
15
- @id, @name = attrs[:id], attrs[:name]
16
- end
17
- end
18
-
19
- class Task
20
- include Dry::Equalizer(:id, :user_id, :title)
21
-
22
- attr_reader :id, :user_id, :title
23
-
24
- def initialize(attrs)
25
- @id, @name, @title = attrs[:id], attrs[:name], attrs[:title]
26
- end
27
- end
28
-
29
- class Tag
30
- include Dry::Equalizer(:id, :task_id, :name)
31
-
32
- attr_reader :id, :task_id, :name
33
-
34
- def initialize(attrs)
35
- @id, @task_id, @name = attrs[:id], attrs[:task_id], attrs[:name]
36
- end
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,66 +0,0 @@
1
- RSpec.shared_context 'plugins' do
2
- before do
3
- module Test
4
- class WrappingInput
5
- def initialize(input)
6
- @input = input || Hash
7
- end
8
- end
9
-
10
- module Timestamps
11
- class InputWithTimestamp < WrappingInput
12
- def [](value)
13
- v = @input[value]
14
- now = Time.now
15
-
16
- if v[:created_at]
17
- v.merge(updated_at: now)
18
- else
19
- v.merge(created_at: now, updated_at: now)
20
- end
21
- end
22
- end
23
-
24
- module ClassInterface
25
- def build(relation, options = {})
26
- super(relation, options.merge(input: InputWithTimestamp.new(input)))
27
- end
28
- end
29
-
30
- def self.included(klass)
31
- super
32
-
33
- klass.extend ClassInterface
34
- end
35
- end
36
-
37
- module UpcaseName
38
- class UpcaseNameInput < WrappingInput
39
- def [](value)
40
- v = @input[value]
41
- v.merge(name: value.fetch(:name).upcase)
42
- end
43
- end
44
-
45
- module ClassInterface
46
- def build(relation, options = {})
47
- super(relation, options.merge(input: UpcaseNameInput.new(options.fetch(:input))))
48
- end
49
- end
50
-
51
- def self.included(klass)
52
- super
53
-
54
- klass.extend ClassInterface
55
- end
56
- end
57
- end
58
-
59
- ROM.plugins do
60
- adapter :sql do
61
- register :timestamps, Test::Timestamps, type: :command
62
- register :upcase_name, Test::UpcaseName, type: :command
63
- end
64
- end
65
- end
66
- end
@@ -1,115 +0,0 @@
1
- RSpec.shared_context 'relations' do
2
- let(:users) { rom.relations[:users] }
3
- let(:tasks) { rom.relations[:tasks] }
4
- let(:tags) { rom.relations[:tags] }
5
- let(:posts) { rom.relations[:posts] }
6
- let(:books) { rom.relations[:books] }
7
-
8
- before do
9
- configuration.relation(:books) do
10
- schema(:books) do
11
- attribute :id, ROM::SQL::Types::Serial
12
- attribute :author_id, ROM::SQL::Types.ForeignKey(:users)
13
- attribute :title, ROM::SQL::Types::String
14
- attribute :created_at, ROM::SQL::Types::Time
15
- attribute :updated_at, ROM::SQL::Types::Time
16
-
17
- associations do
18
- belongs_to :users, as: :author, relation: :authors, foreign_key: :author_id
19
- end
20
- end
21
- end
22
-
23
- configuration.relation(:users) do
24
- schema(infer: true) do
25
- associations do
26
- has_many :posts
27
- has_many :posts, as: :aliased_posts
28
- has_many :labels, through: :posts
29
- has_many :books, foreign_key: :author_id
30
- end
31
- end
32
-
33
- def by_name(name)
34
- where(name: name)
35
- end
36
-
37
- def all
38
- select(:id, :name).order(:name, :id)
39
- end
40
-
41
- def find(criteria)
42
- where(criteria)
43
- end
44
- end
45
-
46
- configuration.relation(:authors) do
47
- schema(:users, infer: true)
48
- end
49
-
50
- configuration.relation(:tasks) do
51
- schema(infer: true) do
52
- associations do
53
- belongs_to :user
54
- belongs_to :users, as: :assignee
55
- end
56
- end
57
-
58
- def find(criteria)
59
- where(criteria)
60
- end
61
-
62
- def for_users(users)
63
- where(user_id: users.map { |u| u[:id] })
64
- end
65
- end
66
-
67
- configuration.relation(:tags) do
68
- schema(infer: true)
69
- end
70
-
71
- configuration.relation(:labels) do
72
- schema(infer: true) do
73
- associations do
74
- has_many :posts_labels
75
- has_many :posts, through: :posts_labels
76
- end
77
- end
78
- end
79
-
80
- configuration.relation(:posts) do
81
- schema(:posts, infer: true) do
82
- associations do
83
- has_many :labels, through: :posts_labels
84
- belongs_to :user, as: :author
85
- end
86
- end
87
- end
88
-
89
- configuration.relation(:posts_labels) do
90
- schema(infer: true) do
91
- associations do
92
- belongs_to :post
93
- belongs_to :label
94
- end
95
- end
96
- end
97
-
98
- configuration.relation(:comments) do
99
- schema(:messages, as: :comments, infer: true) do
100
- associations do
101
- has_many :reactions, relation: :likes
102
- has_many :reactions, relation: :likes, as: :emotions
103
- end
104
- end
105
- end
106
-
107
- configuration.relation(:likes) do
108
- schema(:reactions, as: :likes, infer: true) do
109
- associations do
110
- belongs_to :message, relation: :comments
111
- end
112
- end
113
- end
114
- end
115
- end