rom-repository 0.0.1 → 0.0.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: 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