rom-repository 0.0.1 → 0.0.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: 4ae5380662bd3fb3fb249bf893a491bb0accbb35
4
- data.tar.gz: 43da8d866c970abe7d471a19ccee12d9882d6d87
3
+ metadata.gz: ddf55be4802e4f11c814bf9452e1fcb6e02a71a6
4
+ data.tar.gz: 9de11b947549b756500724055a45e73723d4cab6
5
5
  SHA512:
6
- metadata.gz: c9fb3246025ba68d17f37e4364263975dba15776c9e516ea9caabb982a22b54555c9ab1ca8fb1eeaebae767b75c514b5aa2e06b3a550675e3cd4f7d23724b0f2
7
- data.tar.gz: 0cde9b16532c6ab85b063480af8bacba6e05f668710752a3f94b07f4685ea0250a203dde2019565019dd3df6a258872085ebfb0fd16dc0ae49fc29356a501c75
6
+ metadata.gz: 155c3435da829762d9d10a15f5baf688f6bb4313ffef93ffee9b4d7e9d341c667c4d49dbb41145e6e53efa44e0cfbe592bac6522e08da457b95f16200703a3cd
7
+ data.tar.gz: a4c944bf075bbb56f3afaa74bfd5e53c5393b38261c191af05ce69dc12f42e4c0ae19e4e3a805dacab1d8fcfb5625bca2a1d618f141018ad5bf0eb2d7ca64929
data/Gemfile CHANGED
@@ -4,6 +4,7 @@ gemspec
4
4
 
5
5
  gem 'rom', github: 'rom-rb/rom', branch: 'master'
6
6
  gem 'rom-sql', github: 'rom-rb/rom-sql', branch: 'master'
7
+
7
8
  gem 'inflecto'
8
9
 
9
10
  group :test do
@@ -13,3 +14,5 @@ group :test do
13
14
  gem 'pg_jruby', platforms: :jruby
14
15
  gem "codeclimate-test-reporter", require: nil
15
16
  end
17
+
18
+ gem 'benchmark-ips'
@@ -1,2 +1,20 @@
1
1
  require 'rom'
2
+
3
+ require 'rom/plugins/relation/view'
4
+ require 'rom/plugins/relation/key_inference'
5
+
6
+ require 'rom/plugins/relation/sql/base_view'
7
+ require 'rom/plugins/relation/sql/auto_combine'
8
+ require 'rom/plugins/relation/sql/auto_wrap'
9
+
2
10
  require 'rom/repository/base'
11
+
12
+ if defined?(ROM::SQL)
13
+ class ROM::SQL::Relation < ROM::Relation
14
+ use :key_inference
15
+ use :view
16
+ use :base_view
17
+ use :auto_combine
18
+ use :auto_wrap
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ module ROM
2
+ module Plugins
3
+ module Relation
4
+ module KeyInference
5
+ # Infer foreign_key name for this relation
6
+ #
7
+ # TODO: this should be configurable and handled by an injected policy
8
+ #
9
+ # @return [Symbol]
10
+ #
11
+ # @api private
12
+ def foreign_key
13
+ :"#{Inflector.singularize(name)}_id"
14
+ end
15
+
16
+ # Return base name which defaults to name attribute
17
+ #
18
+ # @return [Symbol]
19
+ #
20
+ # @api private
21
+ def base_name
22
+ name
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ plugins do
29
+ register :key_inference, Plugins::Relation::KeyInference, type: :relation
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ module ROM
2
+ module Plugins
3
+ module Relation
4
+ module SQL
5
+ module AutoCombine
6
+ # @api private
7
+ def self.included(klass)
8
+ super
9
+ klass.class_eval do
10
+ include(InstanceInterface)
11
+ extend(ClassInterface)
12
+ end
13
+ end
14
+
15
+ module ClassInterface
16
+ def inherited(klass)
17
+ super
18
+ klass.auto_curry :for_combine
19
+ end
20
+ end
21
+
22
+ module InstanceInterface
23
+ # Default methods for fetching combined relation
24
+ #
25
+ # This method is used by default by `combine`
26
+ #
27
+ # @return [SQL::Relation]
28
+ #
29
+ # @api private
30
+ def for_combine(keys, relation)
31
+ pk, fk = keys.to_a.flatten
32
+ where(fk => relation.map { |tuple| tuple[pk] })
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ plugins do
41
+ adapter :sql do
42
+ register :auto_combine, Plugins::Relation::SQL::AutoCombine, type: :relation
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,48 @@
1
+ module ROM
2
+ module Plugins
3
+ module Relation
4
+ module SQL
5
+ module AutoWrap
6
+ # @api private
7
+ def self.included(klass)
8
+ super
9
+ klass.class_eval do
10
+ include(InstanceInterface)
11
+ extend(ClassInterface)
12
+ end
13
+ end
14
+
15
+ module ClassInterface
16
+ def inherited(klass)
17
+ super
18
+ klass.auto_curry :for_wrap
19
+ end
20
+ end
21
+
22
+ module InstanceInterface
23
+ # Default methods for fetching wrapped relation
24
+ #
25
+ # This method is used by default by `wrap` and `wrap_parents`
26
+ #
27
+ # @return [SQL::Relation]
28
+ #
29
+ # @api private
30
+ def for_wrap(keys, name)
31
+ other = __registry__[name]
32
+
33
+ inner_join(name, keys)
34
+ .select(*qualified.header.columns)
35
+ .select_append(*other.prefix(other.name).qualified.header)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ plugins do
44
+ adapter :sql do
45
+ register :auto_wrap, Plugins::Relation::SQL::AutoWrap, type: :relation
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,29 @@
1
+ module ROM
2
+ module Plugins
3
+ module Relation
4
+ module SQL
5
+ module BaseView
6
+ # @api private
7
+ def self.included(klass)
8
+ super
9
+ klass.class_eval do
10
+ def self.inherited(other)
11
+ super
12
+ other.view(:base) do
13
+ header { dataset.columns }
14
+ relation { select(*attributes(:base)).order(primary_key) }
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ plugins do
25
+ adapter :sql do
26
+ register :base_view, Plugins::Relation::SQL::BaseView, type: :relation
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,75 @@
1
+ require 'rom/plugins/relation/view/dsl'
2
+
3
+ module ROM
4
+ module Plugins
5
+ module Relation
6
+ module View
7
+ def self.included(klass)
8
+ super
9
+
10
+ klass.class_eval do
11
+ extend ClassInterface
12
+
13
+ def self.attributes
14
+ @__attributes__ ||= {}
15
+ end
16
+ end
17
+ end
18
+
19
+ # Return column names that will be selected for this relation
20
+ #
21
+ # By default we use dataset columns but first we look at configured
22
+ # attributes by `view` DSL
23
+ #
24
+ # @return [Array<Symbol>]
25
+ #
26
+ # @api private
27
+ def attributes(view_name = name)
28
+ header = self.class.attributes
29
+ .fetch(view_name, self.class.attributes.fetch(:base))
30
+
31
+ if header.is_a?(Proc)
32
+ instance_exec(&header)
33
+ else
34
+ header
35
+ end
36
+ end
37
+
38
+ module ClassInterface
39
+ # Define a relation view with a specific header
40
+ #
41
+ # With headers defined all the mappers will be inferred automatically
42
+ #
43
+ # @example
44
+ # class Users < ROM::Relation[:sql]
45
+ # view(:by_name, [:id, :name]) do |name|
46
+ # where(name: name)
47
+ # end
48
+ #
49
+ # view(:listing, [:id, :name, :email]) do
50
+ # select(:id, :name, :email).order(:name)
51
+ # end
52
+ # end
53
+ #
54
+ # @api public
55
+ def view(*args, &block)
56
+ name, names, relation_block =
57
+ if block.arity == 0
58
+ DSL.new(*args, &block).call
59
+ else
60
+ [*args, block]
61
+ end
62
+
63
+ attributes[name] = names
64
+
65
+ define_method(name, &relation_block)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ plugins do
73
+ register :view, Plugins::Relation::View, type: :relation
74
+ end
75
+ end
@@ -0,0 +1,32 @@
1
+ module ROM
2
+ module Plugins
3
+ module Relation
4
+ module View
5
+ class DSL
6
+ attr_reader :name
7
+
8
+ attr_reader :attributes
9
+
10
+ attr_reader :relation_block
11
+
12
+ def initialize(name, &block)
13
+ @name = name
14
+ instance_eval(&block)
15
+ end
16
+
17
+ def header(*args, &block)
18
+ @attributes = args.size > 0 ? args.first : block
19
+ end
20
+
21
+ def relation(&block)
22
+ @relation_block = lambda(&block)
23
+ end
24
+
25
+ def call
26
+ [name, attributes, relation_block]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,124 +1,10 @@
1
- require 'rom/repository/ext/relation/view_dsl'
1
+ require 'rom/relation/curried'
2
2
 
3
3
  module ROM
4
- module SQL
5
- # A bunch of extensions that will be ported to other adapters
6
- #
7
- # @api public
8
- class Relation < ROM::Relation
9
- # @api private
10
- def self.inherited(klass)
11
- super
12
- klass.class_eval do
13
- exposed_relations.merge(Set[:columns, :for_combine, :for_wrap])
14
-
15
- defines :attributes
16
- attributes({})
17
-
18
- option :attributes, reader: true, default: -> relation { relation.class.attributes }
19
- end
20
- end
21
-
22
- # Define a relation view with a specific header
23
- #
24
- # With headers defined all the mappers will be inferred automatically
25
- #
26
- # @example
27
- # class Users < ROM::Relation[:sql]
28
- # view(:by_name, [:id, :name]) do |name|
29
- # where(name: name)
30
- # end
31
- #
32
- # view(:listing, [:id, :name, :email]) do
33
- # select(:id, :name, :email).order(:name)
34
- # end
35
- # end
36
- #
37
- # @api public
38
- def self.view(*args, &block)
39
- name, names, relation_block =
40
- if block.arity == 0
41
- ViewDSL.new(*args, &block).call
42
- else
43
- [*args, block]
44
- end
45
-
46
- attributes[name] = names
47
-
48
- define_method(name, &relation_block)
49
- end
50
-
51
- # Return column names that will be selected for this relation
52
- #
53
- # By default we use dataset columns but first we look at configured
54
- # attributes by `view` DSL
55
- #
56
- # @return [Array<Symbol>]
57
- #
58
- # @api private
59
- def columns
60
- self.class.attributes.fetch(name, dataset.columns)
61
- end
62
-
63
- # Default methods for fetching combined relation
64
- #
65
- # This method is used by default by `combine`
66
- #
67
- # @return [SQL::Relation]
68
- #
69
- # @api private
70
- def for_combine(keys, relation)
71
- pk, fk = keys.to_a.flatten
72
- where(fk => relation.map { |tuple| tuple[pk] })
73
- end
74
-
75
- # Default methods for fetching wrapped relation
76
- #
77
- # This method is used by default by `wrap` and `wrap_parents`
78
- #
79
- # @return [SQL::Relation]
80
- #
81
- # @api private
82
- def for_wrap(name, keys)
83
- other = __registry__[name]
84
-
85
- inner_join(name, keys)
86
- .select(*qualified.header.columns)
87
- .select_append(*other.prefix(other.name).qualified.header)
88
- end
89
-
90
- # Infer foreign_key name for this relation
91
- #
92
- # TODO: this should be configurable and handled by an injected policy
93
- #
94
- # @return [Symbol]
95
- #
96
- # @api private
97
- def foreign_key
98
- :"#{Inflector.singularize(name)}_id"
99
- end
100
- end
101
- end
102
-
103
- # TODO: remove this once Relation::Lazy is gone
104
4
  class Relation
105
- class Lazy
106
- def base_name
107
- relation.name
108
- end
109
-
110
- def primary_key
111
- relation.primary_key
112
- end
113
-
114
- def foreign_key
115
- relation.foreign_key
116
- end
117
- end
118
-
119
- class Curried < Lazy
120
- def columns
121
- relation.attributes.fetch(options[:name], relation.columns)
5
+ class Curried
6
+ def attributes(view_name = name)
7
+ relation.attributes(view_name)
122
8
  end
123
9
  end
124
10
  end
@@ -11,8 +11,8 @@ module ROM
11
11
  #
12
12
  # @api public
13
13
  class LoadingProxy
14
- include Relation::Materializable
15
14
  include Options
15
+ include Relation::Materializable
16
16
 
17
17
  include LoadingProxy::Combine
18
18
  include LoadingProxy::Wrap
@@ -55,13 +55,13 @@ module ROM
55
55
  #
56
56
  # @api private
57
57
  def to_ast
58
- attr_ast = columns.map { |name| [:attribute, name] }
58
+ attr_ast = attributes.map { |name| [:attribute, name] }
59
59
 
60
60
  node_ast = nodes.map(&:to_ast)
61
61
  wrap_ast = wraps.map(&:to_ast)
62
62
 
63
63
  wrap_attrs = wraps.flat_map { |wrap|
64
- wrap.columns.map { |c| [:attribute, :"#{wrap.base_name}_#{c}"] }
64
+ wrap.attributes.map { |c| [:attribute, :"#{wrap.base_name}_#{c}"] }
65
65
  }
66
66
 
67
67
  meta = options[:meta].merge(base_name: relation.base_name)
@@ -120,6 +120,15 @@ module ROM
120
120
  options[:meta]
121
121
  end
122
122
 
123
+ # Return all nodes that this relation combines
124
+ #
125
+ # @return [Array<LoadingProxy>]
126
+ #
127
+ # @api private
128
+ def nodes
129
+ relation.respond_to?(:nodes) ? relation.nodes : []
130
+ end
131
+
123
132
  private
124
133
 
125
134
  # Return a new instance with another relation and options
@@ -131,15 +140,6 @@ module ROM
131
140
  self.class.new(relation, options.merge(new_options))
132
141
  end
133
142
 
134
- # Return all nodes that this relation combines
135
- #
136
- # @return [Array<LoadingProxy>]
137
- #
138
- # @api private
139
- def nodes
140
- relation.is_a?(Relation::Graph) ? relation.nodes : []
141
- end
142
-
143
143
  # Return all nodes that this relation wraps
144
144
  #
145
145
  # @return [Array<LoadingProxy>]
@@ -159,7 +159,7 @@ module ROM
159
159
  if relation.respond_to?(meth)
160
160
  result = relation.__send__(meth, *args)
161
161
 
162
- if result.is_a?(Relation::Lazy) || result.is_a?(Relation::Graph) || result.is_a?(Relation::Composite)
162
+ if result.kind_of?(Relation::Materializable) && !result.is_a?(Relation::Loaded)
163
163
  __new__(result)
164
164
  else
165
165
  result
@@ -21,7 +21,7 @@ module ROM
21
21
  }
22
22
 
23
23
  relation = wraps.reduce(self) { |a, e|
24
- a.relation.for_wrap(e.base_name, e.meta.fetch(:keys))
24
+ a.relation.for_wrap(e.meta.fetch(:keys), e.base_name)
25
25
  }
26
26
 
27
27
  __new__(relation, meta: { wraps: wraps })
@@ -4,6 +4,6 @@ module ROM
4
4
  end
5
5
 
6
6
  class Repository < Gateway
7
- VERSION = '0.0.1'.freeze
7
+ VERSION = '0.0.2'.freeze
8
8
  end
9
9
  end
@@ -16,8 +16,9 @@ Gem::Specification.new do |gem|
16
16
  gem.license = 'MIT'
17
17
 
18
18
  gem.add_runtime_dependency 'anima', '~> 0.2', '>= 0.2'
19
- gem.add_runtime_dependency 'rom', '~> 0.8', '>= 0.8.1'
20
- gem.add_runtime_dependency 'rom-sql', '~> 0.5', '>= 0.5.3'
19
+ gem.add_runtime_dependency 'rom', '~> 0.9.0.beta1'
20
+ gem.add_runtime_dependency 'rom-support', '~> 0.1', '>= 0.1.0'
21
+ gem.add_runtime_dependency 'rom-mapper', '~> 0.2', '>= 0.2.0'
21
22
 
22
23
  gem.add_development_dependency 'rake', '~> 10.3'
23
24
  gem.add_development_dependency 'rspec', '~> 3.3'
@@ -9,8 +9,8 @@ if RUBY_ENGINE == "rbx"
9
9
  CodeClimate::TestReporter.start
10
10
  end
11
11
 
12
- require 'rom-repository'
13
12
  require 'rom-sql'
13
+ require 'rom-repository'
14
14
 
15
15
  begin
16
16
  require 'byebug'
@@ -41,3 +41,5 @@ RSpec.configure do |config|
41
41
 
42
42
  config.include(MapperRegistry)
43
43
  end
44
+
45
+ ROM.use :auto_registration
@@ -5,14 +5,10 @@ RSpec.describe 'SQL Relation extensions' do
5
5
  let(:users) { rom.relation(:users) }
6
6
 
7
7
  it 'has valid column names' do
8
- expect(users.columns).to eql([:id, :name])
8
+ expect(users.attributes).to eql([:id, :name])
9
9
 
10
- expect(users.by_id.columns).to eql([:name])
11
- expect(users.by_id(1).columns).to eql([:name])
12
- end
13
-
14
- it 'defines a valid method with correct arity' do
15
- expect(users.relation.method(:by_id).arity).to be(1)
10
+ expect(users.by_id.attributes).to eql([:name])
11
+ expect(users.by_id(1).attributes).to eql([:name])
16
12
  end
17
13
  end
18
14
 
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: 0.0.1
4
+ version: 0.0.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: 2015-08-05 00:00:00.000000000 Z
11
+ date: 2015-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anima
@@ -36,40 +36,54 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '0.8'
39
+ version: 0.9.0.beta1
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.9.0.beta1
47
+ - !ruby/object:Gem::Dependency
48
+ name: rom-support
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.1'
40
54
  - - ">="
41
55
  - !ruby/object:Gem::Version
42
- version: 0.8.1
56
+ version: 0.1.0
43
57
  type: :runtime
44
58
  prerelease: false
45
59
  version_requirements: !ruby/object:Gem::Requirement
46
60
  requirements:
47
61
  - - "~>"
48
62
  - !ruby/object:Gem::Version
49
- version: '0.8'
63
+ version: '0.1'
50
64
  - - ">="
51
65
  - !ruby/object:Gem::Version
52
- version: 0.8.1
66
+ version: 0.1.0
53
67
  - !ruby/object:Gem::Dependency
54
- name: rom-sql
68
+ name: rom-mapper
55
69
  requirement: !ruby/object:Gem::Requirement
56
70
  requirements:
57
71
  - - "~>"
58
72
  - !ruby/object:Gem::Version
59
- version: '0.5'
73
+ version: '0.2'
60
74
  - - ">="
61
75
  - !ruby/object:Gem::Version
62
- version: 0.5.3
76
+ version: 0.2.0
63
77
  type: :runtime
64
78
  prerelease: false
65
79
  version_requirements: !ruby/object:Gem::Requirement
66
80
  requirements:
67
81
  - - "~>"
68
82
  - !ruby/object:Gem::Version
69
- version: '0.5'
83
+ version: '0.2'
70
84
  - - ">="
71
85
  - !ruby/object:Gem::Version
72
- version: 0.5.3
86
+ version: 0.2.0
73
87
  - !ruby/object:Gem::Dependency
74
88
  name: rake
75
89
  requirement: !ruby/object:Gem::Requirement
@@ -113,6 +127,12 @@ files:
113
127
  - README.md
114
128
  - Rakefile
115
129
  - lib/rom-repository.rb
130
+ - lib/rom/plugins/relation/key_inference.rb
131
+ - lib/rom/plugins/relation/sql/auto_combine.rb
132
+ - lib/rom/plugins/relation/sql/auto_wrap.rb
133
+ - lib/rom/plugins/relation/sql/base_view.rb
134
+ - lib/rom/plugins/relation/view.rb
135
+ - lib/rom/plugins/relation/view/dsl.rb
116
136
  - lib/rom/repository/base.rb
117
137
  - lib/rom/repository/ext/relation.rb
118
138
  - lib/rom/repository/ext/relation/view_dsl.rb