rom-repository 1.3.1 → 1.3.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c74e20a5f12fce2888ae33bfeba0f4ff2baa9546
4
- data.tar.gz: 816d5902836dfe8ab67f785c448c7e1b33b42853
3
+ metadata.gz: 3d274cac190d09e34254d67581d2cd8647e30301
4
+ data.tar.gz: 39db9816c2762e1c47422df900b85d4d82b91556
5
5
  SHA512:
6
- metadata.gz: 9b8dac9fd33b64b269353b52dc6d01a5f2d65a6f97376d2df322ea9bb64fa1a31850100b2080e8b69b89c15a84227cb6e6f02913fcfda673554f1cbb2f0f8539
7
- data.tar.gz: a8355e2936bf75d78ce989337815b0a5446aa532e2fa5e93e359cc87bb920db82afecd3f6a899306d3994e0aab75956a17adda086bb8909075849911eea11da5
6
+ metadata.gz: 55676bbb6a54903a047c3218334038039e8a26d3239ddec34011cef262450f6ed56a63bc0074c1094ebc5d547a845f8ffa20c0ad8ec9b4d5feed2c1eabcb7e09
7
+ data.tar.gz: 9e04a30eecd17b3741f22c3efac94f7a643d73b68dd781bf15e80f37a00be65eb2c5cdb13214ad0b3016e0fe877df7478c6a1c958dd08af654d345ca27880e4e
data/.travis.yml CHANGED
@@ -8,13 +8,16 @@ before_script:
8
8
  - rvm get master
9
9
  script: "bundle exec rake ci"
10
10
  after_success:
11
- - '[ "${TRAVIS_JOB_NUMBER#*.}" = "1" ] && [ "$TRAVIS_BRANCH" = "master" ] && bundle exec codeclimate-test-reporter'
11
+ - '[ -d coverage ] && bundle exec codeclimate-test-reporter'
12
12
  rvm:
13
- - 2.4.0
14
- - 2.3
15
- - 2.2
13
+ - 2.2.7
14
+ - 2.3.4
15
+ - 2.4.1
16
16
  - rbx-3
17
- - jruby-9.1.6.0
17
+ - jruby-9.1.8.0
18
+ matrix:
19
+ allow_failures:
20
+ - rvm: rbx-3
18
21
  env:
19
22
  global:
20
23
  - JRUBY_OPTS='--dev -J-Xmx1024M'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # v1.3.2 2017-05-02
2
+
3
+ ### Fixed
4
+
5
+ * Fix building changesets with relation using `Root#changeset` (flash-gordon)
6
+ * Fix wrap when aliased relation is used (solnic)
7
+ * Fix accessing `data` in map block in changesets (flash-gordon+solnic)
8
+
9
+ ### Changed
10
+
11
+ * Calculate diff only with respect to keys present on the original tuple (yuszuv+solnic)
12
+
1
13
  # v1.3.1 2017-03-25
2
14
 
3
15
  ### Fixed
@@ -7,6 +7,10 @@ module ROM
7
7
  # @api public
8
8
  class Create < Stateful
9
9
  command_type :create
10
+
11
+ def command
12
+ super.new(relation)
13
+ end
10
14
  end
11
15
  end
12
16
  end
@@ -18,7 +18,7 @@ module ROM
18
18
  # @!attribute [r] pipe
19
19
  # @return [Changeset::Pipe] data transformation pipe
20
20
  # @api private
21
- option :pipe, accept: [Proc, Pipe], default: -> { self.class.default_pipe(self) }
21
+ option :pipe, reader: false, optional: true
22
22
 
23
23
  # Define a changeset mapping
24
24
  #
@@ -56,7 +56,7 @@ module ROM
56
56
  #
57
57
  # @api public
58
58
  def self.map(&block)
59
- if block.arity.zero?
59
+ if block.parameters.empty?
60
60
  pipes << Class.new(Pipe, &block).new
61
61
  else
62
62
  pipes << Pipe.new(block)
@@ -212,6 +212,15 @@ module ROM
212
212
  %(#<#{self.class} relation=#{relation.name.inspect} data=#{__data__}>)
213
213
  end
214
214
 
215
+ # Data transformation pipe
216
+ #
217
+ # @return [Changeset::Pipe]
218
+ #
219
+ # @api private
220
+ def pipe
221
+ @pipe ||= self.class.default_pipe(self)
222
+ end
223
+
215
224
  private
216
225
 
217
226
  # @api private
@@ -77,8 +77,11 @@ module ROM
77
77
  def diff
78
78
  @diff ||=
79
79
  begin
80
- new_tuple = __data__.to_a
81
- ori_tuple = original.to_a
80
+ data_tuple = __data__.to_a
81
+ data_keys = __data__.keys & original.keys
82
+
83
+ new_tuple = data_tuple.to_a.select { |(k, _)| data_keys.include?(k) }
84
+ ori_tuple = original.to_a.select { |(k, _)| data_keys.include?(k) }
82
85
 
83
86
  Hash[new_tuple - (new_tuple & ori_tuple)]
84
87
  end
@@ -69,7 +69,7 @@ module ROM
69
69
  def wraps_from_names(names)
70
70
  names.map { |name|
71
71
  assoc = associations[name]
72
- registry[assoc.target].wrapped(name, assoc.combine_keys(__registry__), true)
72
+ registry[assoc.target.relation].wrapped(name, assoc.combine_keys(__registry__), true)
73
73
  }
74
74
  end
75
75
  end
@@ -150,7 +150,7 @@ module ROM
150
150
  super
151
151
  elsif args.first.is_a?(Class)
152
152
  klass, *rest = args
153
- super(klass[self.class.root], *rest)
153
+ super(klass[klass.relation || self.class.root], *rest)
154
154
  else
155
155
  super(root.name, *args)
156
156
  end
@@ -1,5 +1,5 @@
1
1
  module ROM
2
2
  class Repository
3
- VERSION = '1.3.1'.freeze
3
+ VERSION = '1.3.2'.freeze
4
4
  end
5
5
  end
@@ -2,6 +2,22 @@ RSpec.describe 'Using changesets' do
2
2
  include_context 'database'
3
3
  include_context 'relations'
4
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
+
5
21
  describe 'Create' do
6
22
  subject(:repo) do
7
23
  Class.new(ROM::Repository[:users]) {
@@ -10,6 +26,18 @@ RSpec.describe 'Using changesets' do
10
26
  }.new(rom)
11
27
  end
12
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
+
13
41
  it 'can be passed to a command' do
14
42
  changeset = repo.changeset(name: "Jane Doe")
15
43
  command = repo.command(:create, repo.users)
@@ -70,6 +98,28 @@ RSpec.describe 'Using changesets' do
70
98
  expect(result.created_at).to be_instance_of(Time)
71
99
  expect(result.updated_at).to be_instance_of(Time)
72
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
73
123
  end
74
124
 
75
125
  describe 'Update' do
@@ -1,8 +1,11 @@
1
+ # coding: utf-8
1
2
  RSpec.describe 'Repository with multi-adapters configuration' do
2
- let!(:configuration) {
3
+ let(:configuration) {
3
4
  ROM::Configuration.new(default: [:sql, DB_URI], memory: [:memory])
4
5
  }
5
6
 
7
+ let(:sql_conn) { configuration.gateways[:default].connection }
8
+
6
9
  let(:rom) { ROM.container(configuration) }
7
10
 
8
11
  let(:users) { rom.relation(:sql_users) }
@@ -11,6 +14,14 @@ RSpec.describe 'Repository with multi-adapters configuration' do
11
14
  let(:repo) { Test::Repository.new(rom) }
12
15
 
13
16
  before do
17
+ [:tags, :tasks, :posts, :books, :users, :posts_labels, :labels,
18
+ :reactions, :messages].each { |table| sql_conn.drop_table?(table) }
19
+
20
+ sql_conn.create_table :users do
21
+ primary_key :id
22
+ column :name, String
23
+ end
24
+
14
25
  module Test
15
26
  class Users < ROM::Relation[:sql]
16
27
  gateway :default
@@ -34,7 +45,7 @@ RSpec.describe 'Repository with multi-adapters configuration' do
34
45
  end
35
46
 
36
47
  def for_users(users)
37
- restrict(user_id: users.map { |u| u[:id] })
48
+ restrict(user_id: users.pluck(:id))
38
49
  end
39
50
  end
40
51
 
@@ -71,6 +71,17 @@ RSpec.describe 'ROM repository' do
71
71
  expect(repo.tag_with_wrapped_task.first).to eql(tag_with_task)
72
72
  end
73
73
 
74
+ it 'loads wraps using aliased relation' do
75
+ author = repo.users.where(name: 'Jane').one
76
+
77
+ repo.command(:create, repo.books).(title: 'Hello World', author_id: author.id)
78
+
79
+ book = repo.books.wrap(:author).to_a.first
80
+
81
+ expect(book.author.id).to eql(author.id)
82
+ expect(book.author.name).to eql(author.name)
83
+ end
84
+
74
85
  it 'loads multiple wraps' do
75
86
  post_label = repo.posts_labels.wrap(:post).wrap(:label).to_a.first
76
87
 
@@ -14,21 +14,22 @@ RSpec.shared_context 'database' do
14
14
  include_context 'database setup'
15
15
 
16
16
  before do
17
- [:tags, :tasks, :posts, :users, :posts_labels, :labels, :books,
17
+ [:tags, :tasks, :posts, :books, :users, :posts_labels, :labels,
18
18
  :reactions, :messages].each { |table| conn.drop_table?(table) }
19
19
 
20
+ conn.create_table :users do
21
+ primary_key :id
22
+ column :name, String
23
+ end
24
+
20
25
  conn.create_table :books do
21
26
  primary_key :id
27
+ foreign_key :author_id, :users, on_delete: :cascade
22
28
  column :title, String
23
29
  column :created_at, Time
24
30
  column :updated_at, Time
25
31
  end
26
32
 
27
- conn.create_table :users do
28
- primary_key :id
29
- column :name, String
30
- end
31
-
32
33
  conn.create_table :tasks do
33
34
  primary_key :id
34
35
  foreign_key :user_id, :users, null: false, on_delete: :cascade
@@ -9,9 +9,14 @@ RSpec.shared_context 'relations' do
9
9
  configuration.relation(:books) do
10
10
  schema(:books) do
11
11
  attribute :id, ROM::SQL::Types::Serial
12
+ attribute :author_id, ROM::SQL::Types.ForeignKey(:users)
12
13
  attribute :title, ROM::SQL::Types::String
13
14
  attribute :created_at, ROM::SQL::Types::Time
14
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
15
20
  end
16
21
  end
17
22
 
@@ -21,6 +26,7 @@ RSpec.shared_context 'relations' do
21
26
  has_many :posts
22
27
  has_many :posts, as: :aliased_posts
23
28
  has_many :labels, through: :posts
29
+ has_many :books, foreign_key: :author_id
24
30
  end
25
31
  end
26
32
 
@@ -37,6 +43,10 @@ RSpec.shared_context 'relations' do
37
43
  end
38
44
  end
39
45
 
46
+ configuration.relation(:authors) do
47
+ schema(:users, infer: true)
48
+ end
49
+
40
50
  configuration.relation(:tasks) do
41
51
  schema(infer: true) do
42
52
  associations do
data/spec/shared/repo.rb CHANGED
@@ -6,7 +6,7 @@ RSpec.shared_context('repo') do
6
6
 
7
7
  let(:repo_class) do
8
8
  Class.new(ROM::Repository[:users]) do
9
- relations :tasks, :tags, :posts, :labels, :posts_labels
9
+ relations :tasks, :tags, :posts, :labels, :posts_labels, :books, :authors
10
10
 
11
11
  def find_users(criteria)
12
12
  users.find(criteria)
data/spec/spec_helper.rb CHANGED
@@ -1,13 +1,17 @@
1
- # encoding: utf-8
2
-
3
1
  # this is needed for guard to work, not sure why :(
4
2
  require "bundler"
5
3
  Bundler.setup
6
4
 
7
- if ENV['COVERAGE'] == 'true' && RUBY_ENGINE == 'ruby' && RUBY_VERSION >= '2.4.0' && ENV['CI'] == 'true'
8
- require 'simplecov'
9
- SimpleCov.start do
10
- add_filter '/spec/'
5
+ if RUBY_ENGINE == 'ruby' && ENV['COVERAGE'] == 'true'
6
+ require 'yaml'
7
+ rubies = YAML.load(File.read(File.join(__dir__, '..', '.travis.yml')))['rvm']
8
+ latest_mri = rubies.select { |v| v =~ /\A\d+\.\d+.\d+\z/ }.max
9
+
10
+ if RUBY_VERSION == latest_mri
11
+ require 'simplecov'
12
+ SimpleCov.start do
13
+ add_filter '/spec/'
14
+ end
11
15
  end
12
16
  end
13
17
 
@@ -61,7 +65,7 @@ Warning.extend(SileneceWarnings) if warning_api_available
61
65
 
62
66
  RSpec.configure do |config|
63
67
  config.disable_monkey_patching!
64
- config.warnings = true
68
+ config.warnings = warning_api_available
65
69
 
66
70
  config.after do
67
71
  Test.remove_constants
@@ -42,6 +42,29 @@ RSpec.describe ROM::Changeset, '.map' do
42
42
  end
43
43
  end
44
44
 
45
+ context 'accessing data in a map block' do
46
+ subject(:changeset) do
47
+ Class.new(ROM::Changeset::Create[:users]) do
48
+ map do |tuple|
49
+ extend_data(tuple)
50
+ end
51
+
52
+ private
53
+
54
+ def extend_data(tuple)
55
+ tuple.merge(email: "#{self[:name].downcase}@test.com")
56
+ end
57
+ end.new(relation).data(user_data)
58
+ end
59
+
60
+ let(:relation) { double(:relation) }
61
+ let(:user_data) { { name: 'Jane' } }
62
+
63
+ it 'extends data in a map block' do
64
+ expect(changeset.to_h).to eql(name: 'Jane', email: 'jane@test.com')
65
+ end
66
+ end
67
+
45
68
  context 'multi mapping with custom blocks' do
46
69
  subject(:changeset) do
47
70
  Class.new(ROM::Changeset::Create[:users]) do
@@ -53,6 +76,10 @@ RSpec.describe ROM::Changeset, '.map' do
53
76
  tuple.merge(two: next_value)
54
77
  end
55
78
 
79
+ map do |three: next_value, **other|
80
+ { three: three, **other }
81
+ end
82
+
56
83
  def initialize(*args)
57
84
  super
58
85
  @counter = 0
@@ -72,7 +99,7 @@ RSpec.describe ROM::Changeset, '.map' do
72
99
  let(:user_data) { { name: 'Jane' } }
73
100
 
74
101
  it 'applies mappings in order of definition' do
75
- expect(changeset.to_h).to eql(name: 'Jane', one: 1, two: 2)
102
+ expect(changeset.to_h).to eql(name: 'Jane', one: 1, two: 2, three: 3)
76
103
  end
77
104
 
78
105
  it 'inherits pipes' do
@@ -32,13 +32,21 @@ RSpec.describe ROM::Changeset do
32
32
 
33
33
  expect(changeset.diff).to eql(name: "Jane Doe")
34
34
  end
35
+
36
+ it 'does not consider keys that are not present on the original tuple' do
37
+ expect(relation).to receive(:one).and_return(jane)
38
+
39
+ changeset = ROM::Changeset::Update.new(relation).data(foo: 'bar')
40
+
41
+ expect(changeset.diff).to eql({})
42
+ end
35
43
  end
36
44
 
37
45
  describe '#diff?' do
38
46
  it 'returns true when data differs from the original tuple' do
39
47
  expect(relation).to receive(:one).and_return(jane)
40
48
 
41
- changeset = ROM::Changeset::Update.new(relation, __data__: { name: "Jane Doe" })
49
+ changeset = ROM::Changeset::Update.new(relation).data(name: "Jane Doe")
42
50
 
43
51
  expect(changeset).to be_diff
44
52
  end
@@ -46,7 +54,15 @@ RSpec.describe ROM::Changeset do
46
54
  it 'returns false when data are equal to the original tuple' do
47
55
  expect(relation).to receive(:one).and_return(jane)
48
56
 
49
- changeset = ROM::Changeset::Update.new(relation, __data__: { name: "Jane" })
57
+ changeset = ROM::Changeset::Update.new(relation).data(name: 'Jane')
58
+
59
+ expect(changeset).to_not be_diff
60
+ end
61
+
62
+ it 'returns false when data contains keys that are not available on the original tuple' do
63
+ expect(relation).to receive(:one).and_return(jane)
64
+
65
+ changeset = ROM::Changeset::Update.new(relation).data(foo: 'bar')
50
66
 
51
67
  expect(changeset).to_not be_diff
52
68
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rom-repository
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-25 00:00:00.000000000 Z
11
+ date: 2017-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rom
@@ -191,7 +191,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
191
191
  version: '0'
192
192
  requirements: []
193
193
  rubyforge_project:
194
- rubygems_version: 2.6.10
194
+ rubygems_version: 2.6.11
195
195
  signing_key:
196
196
  specification_version: 4
197
197
  summary: Repository abstraction for rom-rb