rom-mongo 0.1.0 → 0.2.0

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: 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