rom-mongo 0.1.0 → 0.2.0

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: 8a48989a26577814779425d8ef55181ffa6f3d47
4
- data.tar.gz: 958e7bfea5f3dcf0cf50604c82578ae5bee76313
3
+ metadata.gz: 158a1091649ee8eabb19d094f2537965ea16d920
4
+ data.tar.gz: 7958f09445195f7b0a589045be6b473b5c935f29
5
5
  SHA512:
6
- metadata.gz: 7f9020ddc8ee6d5ab39a9e9231c8493c6e6e38fc021a7009114b15209db384d1d809168384f3577bb0ee4791dbb9b14306bf448572d38e5c1fc0dc145ce37ae5
7
- data.tar.gz: 6ca1c6acf4fa3d06f8500ccd8c1134c4da37c55d101cf9d54866fb258a7f19d15b85913cd3d1c39b26ec8ff2bfe55838ac467d1c5619917dee356b67b11c9ebd
6
+ metadata.gz: baf1b0460b2418e8c4692a77b1d51d5f37cbd2f635d6678ee85ecc8f4c6a3ac1f178d125d89abae0ee251fd9535f86ac27b25bcdb309ae9a92cd312f57b1d6ec
7
+ data.tar.gz: 26df9df0b2497306e270f656279a2393b6f1e2b38eaca5a7f6cd470f8cc20fcea9cfa83c97d0a2f7782effcabcd01a7895564cd9778291075a7b55795e4840e0
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --color
2
2
  --order random
3
+ --require ./spec/spec_helper
@@ -1,25 +1,26 @@
1
1
  language: ruby
2
- sudo: false
2
+ dist: trusty
3
+ sudo: required
3
4
  cache: bundler
5
+ services:
6
+ - mongodb
4
7
  bundler_args: --without yard guard benchmarks tools
5
- env:
6
- global:
7
- - JRUBY_OPTS='--dev -J-Xmx1024M'
8
- - CODECLIMATE_REPO_TOKEN=886f3b795e74159719804f8e18b853f4c23a81bd814404e52ec248a0dae6d656
8
+ after_success:
9
+ - '[ -d coverage ] && bundle exec codeclimate-test-reporter'
9
10
  script: "bundle exec rake ci"
10
11
  rvm:
11
- - 2.0
12
- - 2.1
13
- - rbx-2
12
+ - 2.2.6
13
+ - 2.3.3
14
+ - 2.4.1
15
+ - rbx-3
14
16
  - jruby
15
- - jruby-head
16
- - ruby-head
17
+ env:
18
+ global:
19
+ - JRUBY_OPTS='--dev -J-Xmx1024M'
20
+ - COVERAGE='true'
17
21
  matrix:
18
22
  allow_failures:
19
- - rvm: ruby-head
20
- - rvm: jruby-head
21
- services:
22
- - mongodb
23
+ - rvm: rbx-3
23
24
  notifications:
24
25
  webhooks:
25
26
  urls:
@@ -1,3 +1,18 @@
1
+ ## v0.2.0 2017-04-07
2
+
3
+ ### Added
4
+
5
+ * Added `Relation#by_pk` for compability with `rom-repo`'s command compiler (flash-gordon)
6
+ * Support fot inferring relations from collection list (flash-gordon)
7
+ * Support for ordered queries with `Relation#order` (flash-gordon)
8
+
9
+ ### Changed
10
+
11
+ * Updated to use official mongo driver (kwando)
12
+ * `Dataset` uses origin's querable interface now rather than forwarding to collection (kwando)
13
+
14
+ [Compare v0.1.0...v0.2.0](https://github.com/rom-rb/rom-mongo/compare/v0.1.0...v0.2.0)
15
+
1
16
  ## v0.1.0 2014-12-23
2
17
 
3
18
  Update to work with ROM 0.6.0
data/Gemfile CHANGED
@@ -2,12 +2,14 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ gem 'rom', git: 'https://github.com/rom-rb/rom.git', branch: 'master'
6
+ gem 'rom-repository', git: 'https://github.com/rom-rb/rom-repository.git', branch: 'master'
7
+
5
8
  group :test do
6
9
  gem 'inflecto'
7
- gem 'rom', git: 'https://github.com/rom-rb/rom.git', branch: 'master'
8
- gem 'rspec', '~> 3.1'
9
- gem 'codeclimate-test-reporter', require: false
10
- gem 'virtus'
10
+ gem 'codeclimate-test-reporter', require: false, platforms: :mri
11
+ gem 'dry-struct'
12
+ gem 'byebug', platforms: :mri
11
13
  end
12
14
 
13
15
  group :tools do
data/README.md CHANGED
@@ -33,7 +33,10 @@ Or install it yourself as:
33
33
 
34
34
  ## Usage
35
35
 
36
- See [spec/integration/repository_spec.rb](spec/integration/repository_spec.rb) for a sample usage.
36
+ See [spec/integration/gateway_spec.rb](spec/integration/gateway_spec.rb) for a sample usage.
37
+
38
+ ## Issues
39
+ Issues should be reported in the main ROM repository, [https://github.com/rom-rb/rom/issues](https://github.com/rom-rb/rom/issues)
37
40
 
38
41
  ## License
39
42
 
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  require "rspec/core/rake_task"
2
+ require "bundler/gem_tasks"
2
3
 
3
4
  RSpec::Core::RakeTask.new(:spec)
4
5
  task default: [:ci]
@@ -1,6 +1,7 @@
1
1
  require 'rom'
2
2
 
3
3
  require 'rom/mongo/version'
4
- require 'rom/mongo/repository'
4
+ require 'rom/mongo/relation'
5
+ require 'rom/mongo/gateway'
5
6
 
6
7
  ROM.register_adapter(:mongo, ROM::Mongo)
@@ -6,6 +6,8 @@ module ROM
6
6
  module Mongo
7
7
  module Commands
8
8
  class Create < ROM::Commands::Create
9
+ adapter :mongo
10
+
9
11
  def collection
10
12
  relation.dataset
11
13
  end
@@ -17,6 +19,8 @@ module ROM
17
19
  end
18
20
 
19
21
  class Update < ROM::Commands::Update
22
+ adapter :mongo
23
+
20
24
  def collection
21
25
  relation.dataset
22
26
  end
@@ -28,9 +32,11 @@ module ROM
28
32
  end
29
33
 
30
34
  class Delete < ROM::Commands::Delete
35
+ adapter :mongo
36
+
31
37
  def execute
32
- removed = target.to_a
33
- target.dataset.remove_all
38
+ removed = relation.to_a
39
+ relation.dataset.remove_all
34
40
  removed
35
41
  end
36
42
  end
@@ -1,9 +1,91 @@
1
- require 'charlatan'
1
+ require 'origin'
2
2
 
3
3
  module ROM
4
4
  module Mongo
5
5
  class Dataset
6
- include Charlatan.new(:collection, kind: Moped::Query)
6
+ class Criteria
7
+ include Origin::Queryable
8
+ end
9
+
10
+ def initialize(collection, criteria = Criteria.new)
11
+ @collection = collection
12
+ @criteria = criteria
13
+ end
14
+
15
+ attr_reader :collection
16
+
17
+ attr_reader :criteria
18
+
19
+ def find(criteria = {})
20
+ Dataset.new(collection, Criteria.new.where(criteria))
21
+ end
22
+
23
+ def to_a
24
+ view.to_a
25
+ end
26
+
27
+ # @api private
28
+ def each
29
+ view.each { |doc| yield(doc) }
30
+ end
31
+
32
+ def insert(data)
33
+ collection.insert_one(data)
34
+ end
35
+
36
+ def update_all(attributes)
37
+ view.update_many(attributes)
38
+ end
39
+
40
+ def remove_all
41
+ view.delete_many
42
+ end
43
+
44
+ def where(doc)
45
+ dataset(criteria.where(doc))
46
+ end
47
+
48
+ def only(fields)
49
+ dataset(criteria.only(fields))
50
+ end
51
+
52
+ def without(fields)
53
+ dataset(criteria.without(fields))
54
+ end
55
+
56
+ def limit(limit)
57
+ dataset(criteria.limit(limit))
58
+ end
59
+
60
+ def skip(value)
61
+ dataset(criteria.skip(value))
62
+ end
63
+
64
+ def order(value)
65
+ dataset(criteria.order(value))
66
+ end
67
+
68
+ private
69
+
70
+ def view
71
+ with_options(collection.find(criteria.selector), criteria.options)
72
+ end
73
+
74
+ def dataset(criteria)
75
+ Dataset.new(collection, criteria)
76
+ end
77
+
78
+ # Applies given options to the view
79
+ #
80
+ # @api private
81
+ def with_options(view, options)
82
+ map = { fields: :projection }
83
+ options.each do |option, value|
84
+ option = map.fetch(option, option)
85
+ view = view.send(option, value) if view.respond_to?(option)
86
+ end
87
+ view
88
+ end
7
89
  end
8
90
  end
9
91
  end
@@ -0,0 +1,95 @@
1
+ require 'mongo'
2
+ require 'uri'
3
+
4
+ require 'rom/gateway'
5
+
6
+ require 'rom/mongo/dataset'
7
+ require 'rom/mongo/commands'
8
+
9
+ module ROM
10
+ module Mongo
11
+ class Gateway < ROM::Gateway
12
+ adapter :mongo
13
+
14
+ attr_reader :collections
15
+
16
+ # @!attribute [r] options
17
+ # @return [Hash] Gateway options
18
+ attr_reader :options
19
+
20
+ # Initialize an Mongo gateway
21
+ #
22
+ # Gateways are typically initialized via ROM::Configuration object, gateway constructor
23
+ # arguments such as URI and options are passed directly to this constructor
24
+ #
25
+ # @overload initialize(uri)
26
+ # Connects to a database via URI
27
+ #
28
+ # @example
29
+ # ROM.container(:mongo, 'mongodb://127.0.0.1:27017/db_name')
30
+ #
31
+ # @param [String] uri connection URI
32
+ #
33
+ # @overload initialize(uri, options)
34
+ # Connects to a database via URI and options
35
+ #
36
+ # @example
37
+ # ROM.container(:mongo, 'mongodb://127.0.0.1:27017/db_name', inferrable_relations: %i[users posts])
38
+ #
39
+ # @param [String,Symbol] uri connection URI
40
+ #
41
+ # @param [Hash] options connection options
42
+ #
43
+ # @option options [Array<Symbol>] :inferrable_relations
44
+ # A list of collection names that should be inferred. If
45
+ # this is set explicitly to an empty array relations
46
+ # won't be inferred at all
47
+ #
48
+ # @option options [Array<Symbol>] :not_inferrable_relations
49
+ # A list of collection names that should NOT be inferred
50
+ #
51
+ # @overload initialize(connection)
52
+ # Creates a gateway from an existing database connection.
53
+ #
54
+ # @example
55
+ # ROM.container(:mongo, Mongo::Client.new('mongodb://127.0.0.1:27017/db_name'))
56
+ #
57
+ # @param [Mongo::Client] connection a connection instance
58
+ #
59
+ # @return [Mongo::Gateway]
60
+ #
61
+ # @see https://docs.mongodb.com/ruby-driver/master/ MongoDB driver docs
62
+ #
63
+ # @api public
64
+ def initialize(uri, options = EMPTY_HASH)
65
+ @connection = uri.is_a?(::Mongo::Client) ? uri : ::Mongo::Client.new(uri, options)
66
+ @collections = {}
67
+ end
68
+
69
+ # List of defined collections
70
+ #
71
+ # @return [Array<Symbol>] An array with dataset names
72
+ #
73
+ # @api private
74
+ def schema
75
+ connection.database.collection_names.map(&:to_sym)
76
+ end
77
+
78
+ def [](name)
79
+ collections.fetch(name)
80
+ end
81
+
82
+ def dataset(name)
83
+ collections[name] = Dataset.new(connection[name])
84
+ end
85
+
86
+ def dataset?(name)
87
+ connection.database.collection_names.include?(name.to_s)
88
+ end
89
+
90
+ def command_namespace
91
+ Mongo::Commands
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,32 @@
1
+ require 'rom/plugins/relation/key_inference'
2
+
3
+ module ROM
4
+ module Mongo
5
+ class Relation < ROM::Relation
6
+ # @api private
7
+ def self.inherited(klass)
8
+ super
9
+
10
+ klass.auto_curry :by_pk
11
+ end
12
+
13
+ adapter :mongo
14
+
15
+ use :key_inference
16
+
17
+ forward :insert, :find, :only, :without, :skip, :limit, :where, :order
18
+
19
+ # @!method by_pk(id)
20
+ # Return a relation restricted by _id
21
+ #
22
+ # @param id [BSON::ObjectId] Document's PK value
23
+ #
24
+ # @return [Mongo::Relation]
25
+ #
26
+ # @api public
27
+ def by_pk(id)
28
+ find(_id: id)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,5 @@
1
1
  module ROM
2
2
  module Mongo
3
- VERSION = '0.1.0'.freeze
3
+ VERSION = '0.2.0'.freeze
4
4
  end
5
5
  end
@@ -1,4 +1,3 @@
1
- # coding: utf-8
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'rom/mongo/version'
@@ -18,11 +17,12 @@ Gem::Specification.new do |spec|
18
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
18
  spec.require_paths = ["lib"]
20
19
 
21
- spec.add_runtime_dependency "charlatan"
22
- spec.add_runtime_dependency "moped"
23
- spec.add_runtime_dependency "rom", "~> 0.6", ">= 0.6.0"
20
+ spec.add_runtime_dependency "rom", "~> 3.2"
21
+ spec.add_runtime_dependency "mongo", "~> 2.2"
22
+ spec.add_runtime_dependency "origin"
24
23
 
25
24
  spec.add_development_dependency "bundler"
26
25
  spec.add_development_dependency "rake"
27
26
  spec.add_development_dependency "rubocop", "~> 0.28.0"
27
+ spec.add_development_dependency "rspec", "~> 3.5"
28
28
  end
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+ require 'rom-repository'
3
+
4
+ RSpec.describe 'Mongo gateway' do
5
+ include_context 'database'
6
+ include_context 'users'
7
+
8
+ let(:gateway) { container.gateways[:default] }
9
+
10
+ describe 'env#relation' do
11
+ it 'returns mapped object' do
12
+ jane = users.as(:model).by_name('Jane').one!
13
+
14
+ expect(jane.id)
15
+ .to eql(container.relation(:users) { |r| r.find(name: 'Jane') }.one['_id'].to_s)
16
+
17
+ expect(jane.name).to eql('Jane')
18
+ expect(jane.email).to eql('jane@doe.org')
19
+ end
20
+ end
21
+
22
+ describe 'with a repository' do
23
+ let(:repo) do
24
+ Class.new(ROM::Repository[:users]) do
25
+ commands :create, update: :by_pk
26
+ end.new(container)
27
+ end
28
+
29
+ it 'returns auto-mapped structs' do
30
+ jane = repo.users.by_name('Jane').one!
31
+
32
+ expect(jane._id.to_s)
33
+ .to eql(container.relation(:users) { |r| r.find(name: 'Jane') }.one['_id'].to_s)
34
+
35
+ expect(jane.name).to eql('Jane')
36
+ expect(jane.email).to eql('jane@doe.org')
37
+ end
38
+
39
+ it 'uses #by_pk for update commands' do
40
+ repo.update(jane_id, name: 'Jane Doe')
41
+
42
+ expect(repo.users.by_pk(jane_id).one!.name).to eql('Jane Doe')
43
+ end
44
+ end
45
+
46
+ describe 'gateway#dataset?' do
47
+ it 'returns true if a collection exists' do
48
+ expect(gateway.dataset?(:users)).to be(true)
49
+ end
50
+
51
+ it 'returns false if a does not collection exist' do
52
+ expect(gateway.dataset?(:not_here)).to be(false)
53
+ end
54
+ end
55
+
56
+ describe 'commands' do
57
+ let(:commands) { container.command(:users) }
58
+
59
+ describe 'create' do
60
+ it 'inserts a document into collection' do
61
+ id = BSON::ObjectId.new
62
+
63
+ result = commands.try do
64
+ commands.create.call(_id: id, name: 'joe', email: 'a.joe@doe.org')
65
+ end
66
+
67
+ expect(result)
68
+ .to match_array([{ _id: id, name: 'joe', email: 'a.joe@doe.org' }])
69
+ end
70
+ end
71
+
72
+ describe 'update' do
73
+ it 'updates a document in the collection' do
74
+ jane = container.relation(:users).as(:model).by_name('Jane').one!
75
+
76
+ result = commands.try do
77
+ commands.update.by_name('Jane').call(email: 'jane.doe@test.com')
78
+ end
79
+
80
+ expect(result).to match_array(
81
+ [{ '_id' => BSON::ObjectId.from_string(jane.id),
82
+ 'name' => 'Jane',
83
+ 'email' => 'jane.doe@test.com' }]
84
+ )
85
+ end
86
+ end
87
+
88
+ describe 'delete' do
89
+ it 'deletes documents from the collection' do
90
+ jane = container.relation(:users).as(:model).by_name('Jane').one!
91
+ joe = container.relation(:users).as(:model).by_name('Joe').one!
92
+
93
+ result = commands.try { commands.delete.by_name('Joe') }
94
+
95
+ expect(result).to match_array(
96
+ [{ '_id' => BSON::ObjectId.from_string(joe.id),
97
+ 'name' => 'Joe',
98
+ 'email' => 'a.joe@doe.org' }]
99
+ )
100
+
101
+ expect(container.relation(:users).as(:model).all).to match_array([jane])
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+ require 'rom-repository'
3
+
4
+ RSpec.describe 'relation inference' do
5
+ include_context 'database'
6
+
7
+ before do
8
+ connection.database[:posts].create
9
+ connection.database[:tasks].create
10
+ end
11
+
12
+ after do
13
+ connection.database[:posts].drop
14
+ connection.database[:tasks].drop
15
+ end
16
+
17
+ it 'infers all relations by default' do
18
+ expect(container.relation(:posts)).to be_kind_of(ROM::Mongo::Relation)
19
+ expect(container.relation(:tasks)).to be_kind_of(ROM::Mongo::Relation)
20
+ end
21
+
22
+ it 'infers configured relations' do
23
+ configuration.config.gateways.default.inferrable_relations = [:posts]
24
+
25
+ expect(container.relations.elements.key?(:tasks)).to be(false)
26
+ expect(container.relation(:posts)).to be_kind_of(ROM::Mongo::Relation)
27
+ end
28
+
29
+ it 'skips configured relations' do
30
+ configuration.config.gateways.default.not_inferrable_relations = [:posts]
31
+
32
+ expect(container.relations.elements.key?(:posts)).to be(false)
33
+ expect(container.relation(:tasks)).to be_kind_of(ROM::Mongo::Relation)
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+ RSpec.shared_context 'database' do
2
+ let(:container) { ROM.container(configuration) }
3
+ let(:configuration) { ROM::Configuration.new(:mongo, connection) }
4
+ let(:connection) { ::Mongo::Client.new(MONGO_URI) }
5
+
6
+ let(:users) { container.relation(:users) }
7
+ let(:jane_id) { BSON::ObjectId.new }
8
+ end
@@ -0,0 +1,54 @@
1
+ require 'dry-struct'
2
+
3
+ RSpec.shared_context 'users' do
4
+ let(:users) { container.relation(:users) }
5
+ let(:jane_id) { BSON::ObjectId.new }
6
+
7
+ before do
8
+ connection[:users].drop
9
+
10
+ configuration.relation(:users) do
11
+ schema do
12
+ # TODO: we need ROM::Mongo::Types (similar to ROM::SQL::Types)
13
+ attribute :_id, ROM::Types.Definition(BSON::ObjectId)
14
+ attribute :name, ROM::Types::String
15
+ attribute :email, ROM::Types::String
16
+ end
17
+
18
+ def by_name(name)
19
+ find(name: name)
20
+ end
21
+
22
+ def all
23
+ find
24
+ end
25
+ end
26
+
27
+ configuration.commands(:users) do
28
+ define(:create)
29
+ define(:update)
30
+ define(:delete)
31
+ end
32
+
33
+ user_model = Class.new(Dry::Struct) do
34
+ attribute :id, 'coercible.string'
35
+ attribute :name, 'strict.string'
36
+ attribute :email, 'strict.string'
37
+ end
38
+
39
+ configuration.mappers do
40
+ define(:users) do
41
+ model(user_model)
42
+
43
+ register_as :model
44
+
45
+ attribute :id, from: '_id'
46
+ attribute :name, from: 'name'
47
+ attribute :email, from: 'email'
48
+ end
49
+ end
50
+
51
+ container.relations.users.insert(_id: jane_id, name: 'Jane', email: 'jane@doe.org')
52
+ container.relations.users.insert(name: 'Joe', email: 'a.joe@doe.org')
53
+ end
54
+ end
@@ -1,23 +1,46 @@
1
- # encoding: utf-8
1
+ if RUBY_ENGINE == 'ruby' && ENV['COVERAGE'] == 'true'
2
+ require 'yaml'
3
+ rubies = YAML.load(File.read(File.join(__dir__, '..', '.travis.yml')))['rvm']
4
+ latest_mri = rubies.select { |v| v =~ /\A\d+\.\d+.\d+\z/ }.max
2
5
 
3
- if RUBY_ENGINE == 'rbx'
4
- require "codeclimate-test-reporter"
5
- CodeClimate::TestReporter.start
6
+ if RUBY_VERSION == latest_mri
7
+ require 'simplecov'
8
+ SimpleCov.start do
9
+ add_filter '/spec/'
10
+ end
11
+ end
6
12
  end
7
13
 
8
14
  require 'rom-mongo'
9
15
 
16
+ begin
17
+ require 'byebug'
18
+ rescue LoadError
19
+ end
20
+
21
+ MONGO_URI = 'mongodb://127.0.0.1:27017/rom_mongo'.freeze
22
+
23
+ Mongo::Logger.logger = Logger.new(nil)
24
+
10
25
  root = Pathname(__FILE__).dirname
11
26
 
12
- Dir[root.join('shared/*.rb').to_s].each { |f| require f }
27
+ # Namespace holding all objects created during specs
28
+ module Test
29
+ def self.remove_constants
30
+ constants.each(&method(:remove_const))
31
+ end
32
+ end
13
33
 
14
34
  RSpec.configure do |config|
15
- config.before do
16
- @constants = Object.constants
35
+ config.disable_monkey_patching!
36
+
37
+ config.before(:suite) do
38
+ ::Mongo::Client.new(MONGO_URI).database.drop
17
39
  end
18
40
 
19
41
  config.after do
20
- added_constants = Object.constants - @constants
21
- added_constants.each { |name| Object.send(:remove_const, name) }
42
+ Test.remove_constants
22
43
  end
23
44
  end
45
+
46
+ Dir[root.join('shared/*.rb').to_s].each { |f| require f }
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ require 'rom/lint/spec'
4
+
5
+ RSpec.describe ROM::Mongo::Gateway do
6
+ it_behaves_like 'a rom gateway' do
7
+ let(:identifier) { :mongo }
8
+ let(:gateway) { ROM::Mongo::Gateway }
9
+ let(:uri) { MONGO_URI }
10
+ end
11
+ end
@@ -0,0 +1,33 @@
1
+ RSpec.describe ROM::Mongo::Relation do
2
+ include_context 'database'
3
+ include_context 'users'
4
+
5
+ describe '#by_pk' do
6
+ it 'fetches a document by _id' do
7
+ expect(users.by_pk(jane_id).one!).
8
+ to eql(
9
+ '_id' => jane_id,
10
+ 'name' => 'Jane',
11
+ 'email' => 'jane@doe.org'
12
+ )
13
+ end
14
+ end
15
+
16
+ describe '#order' do
17
+ it 'sorts documents' do
18
+ expect(users.order(name: :asc).only(:name).without(:_id).to_a).
19
+ to eql([{'name' => 'Jane',}, {'name' => 'Joe'}])
20
+
21
+ expect(users.order(name: :desc).only(:name).without(:_id).to_a).
22
+ to eql([{'name' => 'Joe',}, {'name' => 'Jane'}])
23
+ end
24
+
25
+ it 'supports mutli-field sorting' do
26
+ expect(users.order(name: :asc, email: :asc).only(:name).without(:_id).to_a).
27
+ to eql([{'name' => 'Jane',}, {'name' => 'Joe'}])
28
+
29
+ expect(users.order(email: :asc, name: :asc).only(:name).without(:_id).to_a).
30
+ to eql([{'name' => 'Joe',}, {'name' => 'Jane'}])
31
+ end
32
+ end
33
+ end
metadata CHANGED
@@ -1,63 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rom-mongo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
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-03-23 00:00:00.000000000 Z
11
+ date: 2017-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: charlatan
14
+ name: rom
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '3.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '3.2'
27
27
  - !ruby/object:Gem::Dependency
28
- name: moped
28
+ name: mongo
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '2.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '2.2'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rom
42
+ name: origin
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.6'
48
45
  - - ">="
49
46
  - !ruby/object:Gem::Version
50
- version: 0.6.0
47
+ version: '0'
51
48
  type: :runtime
52
49
  prerelease: false
53
50
  version_requirements: !ruby/object:Gem::Requirement
54
51
  requirements:
55
- - - "~>"
56
- - !ruby/object:Gem::Version
57
- version: '0.6'
58
52
  - - ">="
59
53
  - !ruby/object:Gem::Version
60
- version: 0.6.0
54
+ version: '0'
61
55
  - !ruby/object:Gem::Dependency
62
56
  name: bundler
63
57
  requirement: !ruby/object:Gem::Requirement
@@ -100,6 +94,20 @@ dependencies:
100
94
  - - "~>"
101
95
  - !ruby/object:Gem::Version
102
96
  version: 0.28.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.5'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.5'
103
111
  description: MongoDB support for Ruby Object Mapper
104
112
  email:
105
113
  - piotr.solnica@gmail.com
@@ -121,12 +129,17 @@ files:
121
129
  - lib/rom/mongo.rb
122
130
  - lib/rom/mongo/commands.rb
123
131
  - lib/rom/mongo/dataset.rb
124
- - lib/rom/mongo/repository.rb
132
+ - lib/rom/mongo/gateway.rb
133
+ - lib/rom/mongo/relation.rb
125
134
  - lib/rom/mongo/version.rb
126
135
  - rom-mongo.gemspec
127
- - spec/integration/repository_spec.rb
136
+ - spec/integration/gateway_spec.rb
137
+ - spec/integration/inference_spec.rb
138
+ - spec/shared/database.rb
139
+ - spec/shared/users.rb
128
140
  - spec/spec_helper.rb
129
- - spec/unit/repository_spec.rb
141
+ - spec/unit/gateway_spec.rb
142
+ - spec/unit/relation_spec.rb
130
143
  homepage: ''
131
144
  licenses:
132
145
  - MIT
@@ -147,11 +160,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
160
  version: '0'
148
161
  requirements: []
149
162
  rubyforge_project:
150
- rubygems_version: 2.4.5
163
+ rubygems_version: 2.6.11
151
164
  signing_key:
152
165
  specification_version: 4
153
166
  summary: MongoDB support for Ruby Object Mapper
154
167
  test_files:
155
- - spec/integration/repository_spec.rb
168
+ - spec/integration/gateway_spec.rb
169
+ - spec/integration/inference_spec.rb
170
+ - spec/shared/database.rb
171
+ - spec/shared/users.rb
156
172
  - spec/spec_helper.rb
157
- - spec/unit/repository_spec.rb
173
+ - spec/unit/gateway_spec.rb
174
+ - spec/unit/relation_spec.rb
@@ -1,42 +0,0 @@
1
- require 'moped'
2
- require 'uri'
3
-
4
- require 'rom/repository'
5
-
6
- require 'rom/mongo/dataset'
7
- require 'rom/mongo/commands'
8
-
9
- module ROM
10
- module Mongo
11
- class Relation < ROM::Relation
12
- forward :insert, :find
13
- end
14
-
15
- class Repository < ROM::Repository
16
- attr_reader :collections
17
-
18
- def initialize(uri)
19
- host, database = uri.split('/')
20
- @connection = Moped::Session.new([host])
21
- @connection.use database
22
- @collections = {}
23
- end
24
-
25
- def [](name)
26
- collections.fetch(name)
27
- end
28
-
29
- def dataset(name)
30
- collections[name] = Dataset.new(connection[name])
31
- end
32
-
33
- def dataset?(name)
34
- connection.collection_names.include?(name.to_s)
35
- end
36
-
37
- def command_namespace
38
- Mongo::Commands
39
- end
40
- end
41
- end
42
- end
@@ -1,128 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'virtus'
4
-
5
- describe 'Mongo repository' do
6
- subject(:rom) { setup.finalize }
7
-
8
- let(:setup) { ROM.setup(:mongo, '127.0.0.1:27017/test') }
9
- let(:repository) { rom.repositories[:default] }
10
-
11
- after do
12
- repository.connection.drop
13
- end
14
-
15
- before do
16
- setup.relation(:users) do
17
- def by_name(name)
18
- find(name: name)
19
- end
20
-
21
- def all
22
- find
23
- end
24
- end
25
-
26
- setup.commands(:users) do
27
- define(:create)
28
- define(:update)
29
- define(:delete)
30
- end
31
-
32
- user_model = Class.new do
33
- include Virtus.value_object
34
-
35
- values do
36
- attribute :id, String
37
- attribute :name, String
38
- attribute :email, String
39
- end
40
- end
41
-
42
- setup.mappers do
43
- define(:users) do
44
- model(user_model)
45
-
46
- register_as :model
47
-
48
- attribute :id, from: '_id'
49
- attribute :name, from: 'name'
50
- attribute :email, from: 'email'
51
- end
52
- end
53
-
54
- rom.relations.users.insert(name: 'Jane', email: 'jane@doe.org')
55
- rom.relations.users.insert(name: 'Joe', email: 'joe@doe.org')
56
- end
57
-
58
- describe 'env#relation' do
59
- it 'returns mapped object' do
60
- jane = rom.relation(:users).as(:model).by_name('Jane').one!
61
-
62
- expect(jane.id)
63
- .to eql(rom.relation(:users) { |r| r.find(name: 'Jane') }.one['_id'].to_s)
64
- expect(jane.name).to eql('Jane')
65
- expect(jane.email).to eql('jane@doe.org')
66
- end
67
- end
68
-
69
- describe 'repository#dataset?' do
70
- it 'returns true if a collection exists' do
71
- expect(repository.dataset?(:users)).to be(true)
72
- end
73
-
74
- it 'returns false if a does not collection exist' do
75
- expect(repository.dataset?(:not_here)).to be(false)
76
- end
77
- end
78
-
79
- describe 'commands' do
80
- let(:commands) { rom.command(:users) }
81
-
82
- describe 'create' do
83
- it 'inserts a document into collection' do
84
- id = BSON::ObjectId.new
85
-
86
- result = commands.try do
87
- commands.create.call(_id: id, name: 'joe', email: 'joe@doe.org')
88
- end
89
-
90
- expect(result)
91
- .to match_array([{ _id: id, name: 'joe', email: 'joe@doe.org' }])
92
- end
93
- end
94
-
95
- describe 'update' do
96
- it 'updates a document in the collection' do
97
- jane = rom.relation(:users).as(:model).by_name('Jane').one!
98
-
99
- result = commands.try do
100
- commands.update.by_name('Jane').set(email: 'jane.doe@test.com')
101
- end
102
-
103
- expect(result).to match_array(
104
- [{ '_id' => BSON::ObjectId.from_string(jane.id),
105
- 'name' => 'Jane',
106
- 'email' => 'jane.doe@test.com' }]
107
- )
108
- end
109
- end
110
-
111
- describe 'delete' do
112
- it 'deletes documents from the collection' do
113
- jane = rom.relation(:users).as(:model).by_name('Jane').one!
114
- joe = rom.relation(:users).as(:model).by_name('Joe').one!
115
-
116
- result = commands.try { commands.delete.by_name('Joe') }
117
-
118
- expect(result).to match_array(
119
- [{ '_id' => BSON::ObjectId.from_string(joe.id),
120
- 'name' => 'Joe',
121
- 'email' => 'joe@doe.org' }]
122
- )
123
-
124
- expect(rom.relation(:users).as(:model).all).to match_array([jane])
125
- end
126
- end
127
- end
128
- end
@@ -1,11 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'rom/lint/spec'
4
-
5
- describe ROM::Mongo::Repository do
6
- it_behaves_like 'a rom repository' do
7
- let(:identifier) { :mongo }
8
- let(:repository) { ROM::Mongo::Repository }
9
- let(:uri) { '127.0.0.1:27017/test' }
10
- end
11
- end