rom-repository 1.3.1 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
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