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.
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