minidoc 0.0.1 → 1.0.0.rc1

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: bab3513e3711be6f000b2087acd5df2c327ed60f
4
- data.tar.gz: 7cc05456284d80bbdba422cf58c93a829c45592b
3
+ metadata.gz: ca8f2d071dcb6f2ef8e43e9d995e36ef0b1d4c6e
4
+ data.tar.gz: 0b0a1037fa259ab0602d2e21401a368495739803
5
5
  SHA512:
6
- metadata.gz: 4d4c5d33c49a995a7d65186a9da8390aac2a0ae87340ad58c38452288bea0c424ac9e7c1d58c77fc171937ae6e1c14a36620df188586b1d5b8ff8dbad5b0638e
7
- data.tar.gz: 8fbe9a2e11e6c9c37a773f41ec0c832bbe99584170fff167aa423488e01522d8d0ef619798a6185272e763abfb4840dd89f240ed4fc1c5fb44b4b6f0a192a06e
6
+ metadata.gz: d5029b2a00f9427603fe3b3e50270959b1333c0312bd8b50fcd5b8b1d1d9144724a1d893e2bc77f6497435047def4f3fe3f9ce4deaeecc8f14639590f9f66ba4
7
+ data.tar.gz: c398c3570ac71d56aef8a27309ab3c8a4321e172ee829403e8050a64542944288f96a750a1fc24e826f3ecfe5a592df4661c3a528b1bc42f725c5de88b6b7dac
@@ -0,0 +1,16 @@
1
+ ---
2
+ engines:
3
+ duplication:
4
+ enabled: true
5
+ config:
6
+ languages:
7
+ - ruby
8
+ fixme:
9
+ enabled: true
10
+ rubocop:
11
+ enabled: true
12
+ ratings:
13
+ paths:
14
+ - "**.rb"
15
+ exclude_paths:
16
+ - test/
@@ -0,0 +1,152 @@
1
+ ################################################################################
2
+ # Metrics
3
+ ################################################################################
4
+
5
+ Metrics/LineLength:
6
+ Enabled: false
7
+
8
+ Metrics/AbcSize:
9
+ Enabled: false
10
+
11
+ ################################################################################
12
+ # Style
13
+ ################################################################################
14
+
15
+ # Executables are conventionally named bin/foo-bar
16
+ Style/FileName:
17
+ Exclude:
18
+ - bin/**/*
19
+
20
+ # We don't (currently) document our code
21
+ Style/Documentation:
22
+ Enabled: false
23
+
24
+ # Always use double-quotes to keep things simple
25
+ Style/StringLiterals:
26
+ EnforcedStyle: double_quotes
27
+
28
+ Style/StringLiteralsInInterpolation:
29
+ EnforcedStyle: double_quotes
30
+
31
+ # Use a trailing comma to keep diffs clean when elements are inserted or removed
32
+ Style/TrailingCommaInArguments:
33
+ EnforcedStyleForMultiline: comma
34
+
35
+ Style/TrailingCommaInLiteral:
36
+ EnforcedStyleForMultiline: comma
37
+
38
+ # We avoid GuardClause because it can result in "suprise return"
39
+ Style/GuardClause:
40
+ Enabled: false
41
+
42
+ # We avoid IfUnlessModifier because it can result in "suprise if"
43
+ Style/IfUnlessModifier:
44
+ Enabled: false
45
+
46
+ # We don't care about the fail/raise distinction
47
+ Style/SignalException:
48
+ EnforcedStyle: only_raise
49
+
50
+ Style/DotPosition:
51
+ EnforcedStyle: trailing
52
+
53
+ # Common globals we allow
54
+ Style/GlobalVars:
55
+ AllowedVariables:
56
+ - "$statsd"
57
+ - "$mongo"
58
+ - "$rollout"
59
+
60
+ # Using english names requires loading an extra module, which is annoying, so
61
+ # we prefer the perl names for consistency.
62
+ Style/SpecialGlobalVars:
63
+ EnforcedStyle: use_perl_names
64
+
65
+ # We have common cases where has_ and have_ make sense
66
+ Style/PredicateName:
67
+ Enabled: true
68
+ NamePrefixBlacklist:
69
+ - is_
70
+
71
+ # We use %w[ ], not %w( ) because the former looks like an array
72
+ Style/PercentLiteralDelimiters:
73
+ PreferredDelimiters:
74
+ "%i": "[]"
75
+ "%I": "[]"
76
+ "%w": "[]"
77
+ "%W": "[]"
78
+
79
+ # Allow "trivial" accessors when defined as a predicate? method
80
+ Style/TrivialAccessors:
81
+ AllowPredicates: true
82
+
83
+ Style/Next:
84
+ Enabled: false
85
+
86
+ # We think it's OK to use the "extend self" module pattern
87
+ Style/ModuleFunction:
88
+ Enabled: false
89
+
90
+ # Disallow extra spacing for token alignment
91
+ Style/ExtraSpacing:
92
+ AllowForAlignment: false
93
+
94
+ # and/or in conditionals has no meaningful difference (only gotchas), so we
95
+ # disallow them there. When used for control flow, the difference in precedence
96
+ # can make for a less noisy expression, as in:
97
+ #
98
+ # x = find_x or raise XNotFound
99
+ #
100
+ Style/AndOr:
101
+ EnforcedStyle: conditionals
102
+
103
+ Style/AlignParameters:
104
+ EnforcedStyle: with_fixed_indentation
105
+
106
+ Style/MultilineOperationIndentation:
107
+ EnforcedStyle: indented
108
+
109
+ Style/AlignHash:
110
+ EnforcedLastArgumentHashStyle: ignore_implicit
111
+
112
+ # This has the behavior we want, but it has a bug in it which produces a lot of false positives
113
+ # https://github.com/bbatsov/rubocop/issues/3462
114
+ # MultilineMethodCallBraceLayout:
115
+ # EnforcedStyle: new_line
116
+
117
+ ################################################################################
118
+ # Performance
119
+ ################################################################################
120
+
121
+ Performance/RedundantMerge:
122
+ Enabled: false
123
+
124
+ ################################################################################
125
+ # Rails - disable things because we're primarily non-rails
126
+ ################################################################################
127
+
128
+ Rails/Delegate:
129
+ Enabled: false
130
+
131
+ Rails/TimeZone:
132
+ Enabled: false
133
+
134
+ ################################################################################
135
+ # Specs - be more lenient on length checks and block styles
136
+ ################################################################################
137
+
138
+ Metrics/ModuleLength:
139
+ Exclude:
140
+ - spec/**/*
141
+
142
+ Metrics/MethodLength:
143
+ Exclude:
144
+ - spec/**/*
145
+
146
+ Style/ClassAndModuleChildren:
147
+ Exclude:
148
+ - spec/**/*
149
+
150
+ Style/BlockDelimiters:
151
+ Exclude:
152
+ - spec/**/*
@@ -1 +1 @@
1
- 1.9.3-p545
1
+ 2.3.1
@@ -6,3 +6,7 @@ rvm:
6
6
  services: mongodb
7
7
  before_install:
8
8
  - gem update bundler
9
+ script:
10
+ - rake
11
+ after_script:
12
+ - CODECLIMATE_REPO_TOKEN=787a2f89b15c637323c7340d65ec17e898ac44480706b4b4122ea040c2a88f1d bundle exec codeclimate-test-reporter
@@ -0,0 +1,39 @@
1
+ # Change log
2
+
3
+ ## master (unreleased)
4
+
5
+ ### New features
6
+
7
+ ### Bug fixes
8
+
9
+ ### Changes
10
+
11
+ ## v1.0.0.rc1 (2016-09-29)
12
+
13
+ ### New features
14
+
15
+ * [#24](https://github.com/codeclimate/minidoc/pull/24): Add `Minidoc.all`. ([@pbrisbin][])
16
+ * [#24](https://github.com/codeclimate/minidoc/pull/24): Add `Minidoc.find_one!`. ([@pbrisbin][])
17
+ * [#28](https://github.com/codeclimate/minidoc/pull/28): Add `Minidoc.find_one_or_initialize`. ([@nporteschaikin][])
18
+ * [#32](https://github.com/codeclimate/minidoc/pull/32): Infer class names for associations when not provided. ([@wfleming][])
19
+
20
+ ### Bug fixes
21
+
22
+ * [#26](https://github.com/codeclimate/minidoc/pull/26): Improve performance of `Minidoc.exists?`. ([@wfleming][])
23
+ * [#31](https://github.com/codeclimate/minidoc/pull/31): Fix `save` dropping some attributes. ([@nporteschaikin][])
24
+ * Improve errors when the user has forgotten to provide database connection information. ([@maxjacobson][])
25
+
26
+ ### Changes
27
+
28
+ * [#23](https://github.com/codeclimate/minidoc/pull/23): Remove `ensure_index`. ([@pbrisbin][])
29
+
30
+ ## v0.0.1 (2016-09-28)
31
+
32
+ Minidoc was originally created by [@brynary][] and has been used in production extensively at Code Climate.
33
+ This is the first version released to rubygems.
34
+
35
+ [@brynary]: https://github.com/brynary
36
+ [@maxjacobson]: https://github.com/maxjacobson
37
+ [@nporteschaikin]: https://github.com/nporteschaikin
38
+ [@pbrisbin]: https://github.com/pbrisbin
39
+ [@wfleming]: https://github.com/wfleming
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at hello@codeclimate.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile CHANGED
@@ -1,2 +1,9 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
+
3
+ gem "minitest"
4
+ gem "mocha"
5
+ gem "rake"
6
+ gem "simplecov"
7
+ gem "codeclimate-test-reporter", "1.0.0.pre.rc2"
8
+
2
9
  gemspec
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Bryan Helmkamp
1
+ Copyright (c) 2016 Bryan Helmkamp
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
- [![Code Climate](https://codeclimate.com/github/brynary/minidoc.svg)](https://codeclimate.com/github/brynary/minidoc)
2
- [![Build Status](https://travis-ci.org/brynary/minidoc.svg)](https://travis-ci.org/brynary/minidoc)
1
+ [![Build Status](https://travis-ci.org/codeclimate/minidoc.svg)](https://travis-ci.org/codeclimate/minidoc)
2
+ [![Gem Version](https://badge.fury.io/rb/minidoc.svg)](http://badge.fury.io/rb/minidoc)
3
+ [![Code Climate](https://codeclimate.com/github/codeclimate/minidoc/badges/gpa.svg)](https://codeclimate.com/github/codeclimate/minidoc)
4
+ [![Test Coverage](https://codeclimate.com/github/codeclimate/minidoc/badges/coverage.svg)](https://codeclimate.com/github/codeclimate/minidoc/coverage)
3
5
 
4
6
  # Minidoc
5
7
 
@@ -27,14 +29,41 @@ things as simple as possible.
27
29
  * Custom query API (just use Mongo)
28
30
  * Callbacks (just define a method like save and call super)
29
31
 
32
+ ## Installation
33
+
34
+ Add this line to your application's Gemfile:
35
+
36
+ ```ruby
37
+ gem "minidoc"
38
+ ```
39
+
40
+ And then execute:
41
+
42
+ ```
43
+ $ bundle
44
+ ```
45
+
46
+ Or install it yourself as:
47
+
48
+ ```
49
+ $ gem install minidoc
50
+ ```
51
+
30
52
  ## Usage
31
53
 
32
- gem "minidoc", "~> 0.0.1"
54
+ ### Setup
55
+
56
+ ```ruby
57
+ Minidoc.connection = Mongo::MongoClient.from_uri("mongodb://localhost")
58
+ Minidoc.database_name = "my_great_app_development"
59
+ ```
33
60
 
34
61
  ### Basics
35
62
 
36
63
  ```ruby
37
64
  class User < Minidoc
65
+ include Minidoc::Timestamps
66
+
38
67
  attribute :name, String
39
68
  attribute :language, String
40
69
  timestamps!
@@ -71,6 +100,53 @@ user.valid? # => true
71
100
 
72
101
  ### Value Objects
73
102
 
103
+ ```ruby
104
+ bryan = User.create(name: "Bryan").as_value
105
+ bryan.name #=> "Bryan"
106
+ bryan.name = "Brian" #=> NoMethodError
107
+ ```
108
+
74
109
  ### Associations
75
110
 
111
+ ```ruby
112
+ class Drink < Minidoc
113
+ include Minidoc::Associations
114
+
115
+ attribute :name, String
116
+
117
+ belongs_to :user
118
+ end
119
+
120
+ bryan = User.create(name: "Bryan")
121
+ drink = Drink.create(name: "Paloma", user: bryan)
122
+ drink.user == bryan #=> true
123
+ ```
124
+
76
125
  ### Read-only records
126
+
127
+ ```ruby
128
+ class DrinkEvents < Minidoc::ReadOnly
129
+ include Minidoc::Timestamps
130
+ timestamps!
131
+ end
132
+
133
+ DrinkEvents.count(created_at: { "$gt": 4.days.ago }) #=> 0
134
+ DrinkEvents.create #=> NoMethodError
135
+ ```
136
+
137
+ ## Contributing
138
+
139
+ Bug reports and pull requests are welcome on GitHub at https://github.com/codeclimate/minidoc. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
140
+
141
+ When making a pull request, please update the [changelog](CHANGELOG.md).
142
+
143
+ ## Releasing
144
+
145
+ * Update the changelog to mark the unreleased changes as part of the new release.
146
+ * Update the version.rb with the new version number
147
+ * Commit and push to master
148
+ * `rake release` which will
149
+ * tag the latest commit based on version.rb
150
+ * push to github
151
+ * push to rubygems
152
+ * Copy the relevant changelog entries into a new [GitHub release](https://github.com/codeclimate/minidoc/releases).
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
- require 'rake/testtask'
2
+ require "rake/testtask"
3
3
 
4
4
  Rake::TestTask.new do |t|
5
5
  t.libs.push "lib"
6
6
  t.ruby_opts = %w[-W0]
7
- t.test_files = FileList['test/*_test.rb']
7
+ t.test_files = FileList["test/*_test.rb"]
8
8
  t.verbose = true
9
9
  end
10
10
 
@@ -4,20 +4,18 @@ require "active_model"
4
4
  require "active_support/core_ext"
5
5
 
6
6
  class Minidoc
7
- VERSION = "0.0.1"
8
-
9
7
  require "minidoc/associations"
10
8
  require "minidoc/connection"
11
9
  require "minidoc/counters"
12
10
  require "minidoc/finders"
13
11
  require "minidoc/grid"
14
- require "minidoc/indexes"
15
12
  require "minidoc/read_only"
16
13
  require "minidoc/record_invalid"
17
14
  require "minidoc/duplicate_key"
18
15
  require "minidoc/timestamps"
19
16
  require "minidoc/validations"
20
17
  require "minidoc/value"
18
+ require "minidoc/version"
21
19
 
22
20
  include Connection
23
21
  include Finders
@@ -235,7 +233,7 @@ private
235
233
  end
236
234
 
237
235
  def update
238
- self.class.collection.update({ _id: id }, attributes)
236
+ self.class.collection.update({ _id: id }, { "$set" => attributes.except(:_id) })
239
237
  end
240
238
 
241
239
  if ActiveSupport.respond_to?(:run_load_hooks)
@@ -9,6 +9,8 @@ module Minidoc::Associations
9
9
  end
10
10
 
11
11
  def belongs_to(association_name, options = {})
12
+ options[:class_name] ||= "#{self.parent.name}::#{association_name.to_s.camelize}"
13
+
12
14
  association_name = association_name.to_sym
13
15
  associations[association_name] = options
14
16
 
@@ -8,12 +8,15 @@ module Minidoc::Connection
8
8
  class_attribute :database_name
9
9
  end
10
10
 
11
+ MissingConfiguration = Class.new(StandardError)
12
+
11
13
  module ClassMethods
12
14
  def collection
13
15
  database[collection_name]
14
16
  end
15
17
 
16
18
  def database
19
+ validate_config
17
20
  connection[database_name]
18
21
  end
19
22
 
@@ -24,5 +27,15 @@ module Minidoc::Connection
24
27
  def collection_name
25
28
  @collection_name ||= name.demodulize.underscore.pluralize
26
29
  end
30
+
31
+ private
32
+
33
+ def validate_config
34
+ if connection.nil?
35
+ raise MissingConfiguration, "Make sure to set Minidoc.connection"
36
+ elsif database_name.nil?
37
+ raise MissingConfiguration, "Make sure to set Minidoc.database_name"
38
+ end
39
+ end
27
40
  end
28
41
  end
@@ -3,7 +3,13 @@ require "active_support/concern"
3
3
  module Minidoc::Finders
4
4
  extend ActiveSupport::Concern
5
5
 
6
+ DocumentNotFoundError = Class.new(StandardError)
7
+
6
8
  module ClassMethods
9
+ def all
10
+ find({})
11
+ end
12
+
7
13
  def first
8
14
  find_one({})
9
15
  end
@@ -13,7 +19,7 @@ module Minidoc::Finders
13
19
  end
14
20
 
15
21
  def exists?(selector = {})
16
- count(selector) > 0
22
+ find_one(selector).present?
17
23
  end
18
24
 
19
25
  def find(id_or_selector, options = {})
@@ -31,6 +37,15 @@ module Minidoc::Finders
31
37
  wrap(collection.find_one(selector, options))
32
38
  end
33
39
 
40
+ def find_one!(query, options = {})
41
+ find_one(query, options) or raise DocumentNotFoundError
42
+ end
43
+
44
+ def find_one_or_initialize(attributes, options = {})
45
+ raise ArgumentError unless attributes.is_a?(Hash)
46
+ find_one(attributes, options) || new(attributes)
47
+ end
48
+
34
49
  def from_db(attrs)
35
50
  doc = new(attrs)
36
51
  doc.instance_variable_set("@new_record", false)
@@ -0,0 +1,3 @@
1
+ class Minidoc
2
+ VERSION = "1.0.0.rc1"
3
+ end
@@ -1,23 +1,24 @@
1
1
  # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "minidoc/version"
5
+
2
6
  Gem::Specification.new do |spec|
3
- spec.name = "minidoc"
4
- spec.version = "0.0.1"
5
- spec.authors = ["Bryan Helmkamp"]
6
- spec.email = ["bryan@brynary.com"]
7
- spec.summary = %q{Lightweight wrapper for MongoDB documents}
8
- spec.homepage = "https://github.com/brynary/minidoc"
9
- spec.license = "MIT"
7
+ spec.name = "minidoc"
8
+ spec.version = Minidoc::VERSION
9
+ spec.authors = ["Bryan Helmkamp", "Code Climate"]
10
+ spec.email = ["bryan@brynary.com", "hello@codeclimate.com"]
11
+ spec.summary = %q{Lightweight wrapper for MongoDB documents}
12
+ spec.homepage = "https://github.com/codeclimate/minidoc"
13
+ spec.license = "MIT"
10
14
 
11
- spec.files = `git ls-files`.split($/)
12
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
13
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
14
18
  spec.require_paths = ["lib"]
15
19
 
16
- spec.add_dependency "activesupport", ">= 3.0.0"
17
- spec.add_dependency "activemodel", ">= 3.0.0"
18
- spec.add_dependency "virtus", "~> 1.0.0"
20
+ spec.add_dependency "activesupport", ">= 3.0.0", "< 5"
21
+ spec.add_dependency "activemodel", ">= 3.0.0", "< 5"
22
+ spec.add_dependency "virtus", "~> 1.0", ">= 1.0.0"
19
23
  spec.add_dependency "mongo", "~> 1"
20
- spec.add_development_dependency "minitest"
21
- spec.add_development_dependency "mocha"
22
- spec.add_development_dependency "rake"
23
24
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class ActiveModelTest < Minidoc::TestCase
4
4
  def test_model_name
@@ -12,13 +12,13 @@ class ActiveModelTest < Minidoc::TestCase
12
12
 
13
13
  def test_to_key
14
14
  user = User.new
15
- user.id = BSON::ObjectId('52955618f9f6a52444000001')
15
+ user.id = BSON::ObjectId("52955618f9f6a52444000001")
16
16
  assert_equal ["52955618f9f6a52444000001"], user.to_key
17
17
  end
18
18
 
19
19
  def test_to_param
20
20
  user = User.new
21
- user.id = BSON::ObjectId('52955618f9f6a52444000001')
21
+ user.id = BSON::ObjectId("52955618f9f6a52444000001")
22
22
  assert_equal "52955618f9f6a52444000001", user.to_param
23
23
  end
24
24
 
@@ -1,4 +1,4 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class BelongsToTest < Minidoc::TestCase
4
4
  class Cat < Minidoc
@@ -6,9 +6,24 @@ class BelongsToTest < Minidoc::TestCase
6
6
  belongs_to :owner, class_name: "User"
7
7
  end
8
8
 
9
+ class ::Dog < Minidoc
10
+ include Minidoc::Associations
11
+ belongs_to :user
12
+ end
13
+
9
14
  class User < ::User
10
15
  end
11
16
 
17
+ module Animal
18
+ class Armadillo < Minidoc
19
+ include Minidoc::Associations
20
+ belongs_to :predator
21
+ end
22
+
23
+ class Predator < Minidoc
24
+ end
25
+ end
26
+
12
27
  def test_loading
13
28
  assert_nil Cat.new.owner
14
29
  user = User.create
@@ -46,4 +61,22 @@ class BelongsToTest < Minidoc::TestCase
46
61
  cat.owner_id = user.id
47
62
  assert_equal "Noah", cat.owner.name # changes
48
63
  end
64
+
65
+ def test_top_level_inferred_class_name
66
+ assert_nil Dog.new.user
67
+ user = User.create
68
+ sam = Dog.new(user_id: user.id)
69
+ assert_equal user.id, sam.user.id
70
+ sam.save
71
+ assert_equal user.id, sam.user.id
72
+ end
73
+
74
+ def test_nested_inferred_class_name
75
+ assert_nil Animal::Armadillo.new.predator
76
+ predator = Animal::Predator.create
77
+ arnie = Animal::Armadillo.new(predator_id: predator.id)
78
+ assert_equal predator.id, arnie.predator.id
79
+ arnie.save
80
+ assert_equal predator.id, arnie.predator.id
81
+ end
49
82
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class ConnectionTest < Minidoc::TestCase
4
4
  class Company < Minidoc
@@ -1,4 +1,4 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class CountersTest < Minidoc::TestCase
4
4
  class SimpleCounter < Minidoc
@@ -1,4 +1,4 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class DuplicateKeyTest < Minidoc::TestCase
4
4
  def test_rescue_duplicate_key_errors_result
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('../helper', __FILE__)
3
+
4
+ class FirstRunTest < Minidoc::TestCase
5
+ def test_missing_setup_values
6
+ with_alternative_configuration do
7
+ Minidoc.connection = nil
8
+ Minidoc.database_name = nil
9
+
10
+ ex =
11
+ assert_raises Minidoc::MissingConfiguration do
12
+ User.create(name: "Kären")
13
+ end
14
+ assert_equal ex.message, "Make sure to set Minidoc.connection"
15
+ end
16
+ end
17
+
18
+ def test_missing_database_name_only
19
+ with_alternative_configuration do
20
+ Minidoc.database_name = nil
21
+
22
+ ex =
23
+ assert_raises Minidoc::MissingConfiguration do
24
+ User.create(name: "Kären")
25
+ end
26
+ assert_equal ex.message, "Make sure to set Minidoc.database_name"
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def with_alternative_configuration
33
+ original_connection = Minidoc.connection
34
+ original_database_name = Minidoc.database_name
35
+ yield
36
+ ensure
37
+ Minidoc.connection = original_connection
38
+ Minidoc.database_name = original_database_name
39
+ end
40
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class GridTest < Minidoc::TestCase
4
4
 
@@ -1,16 +1,29 @@
1
- require 'minidoc'
2
- require 'minidoc/test_helpers'
3
- require 'minitest/autorun'
4
- require 'mocha/mini_test'
1
+ require "simplecov"
2
+ SimpleCov.start do
3
+ add_filter "/test/"
4
+ end
5
+
6
+ require "minidoc"
7
+ require "minidoc/test_helpers"
8
+ require "minitest/autorun"
9
+ require "mocha/mini_test"
5
10
 
6
11
  I18n.enforce_available_locales = false
7
12
  I18n.load_path << File.expand_path("../locale/en.yml", __FILE__)
8
13
 
9
14
  class User < Minidoc
15
+ self.collection_name = "users"
16
+
10
17
  attribute :name, String
11
18
  attribute :age, Integer
12
19
  end
13
20
 
21
+ class SecondUser < Minidoc
22
+ self.collection_name = "users"
23
+
24
+ attribute :age, Integer
25
+ end
26
+
14
27
  $mongo = Mongo::MongoClient.from_uri(ENV["MONGODB_URI"] || "mongodb://localhost")
15
28
  Minidoc.connection = $mongo
16
29
  Minidoc.database_name = "minidoc_test"
@@ -1,15 +1,15 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class PersistenceTest < Minidoc::TestCase
4
4
  def test_ids
5
5
  user = User.new
6
6
  assert_equal BSON::ObjectId, user.id.class
7
7
 
8
- user = User.new(_id: BSON::ObjectId('52955cc5f9f6a538a9000001'))
9
- assert_equal BSON::ObjectId('52955cc5f9f6a538a9000001'), user.id
8
+ user = User.new(_id: BSON::ObjectId("52955cc5f9f6a538a9000001"))
9
+ assert_equal BSON::ObjectId("52955cc5f9f6a538a9000001"), user.id
10
10
 
11
- user = User.new("_id" => BSON::ObjectId('52955cc5f9f6a538a9000001'))
12
- assert_equal BSON::ObjectId('52955cc5f9f6a538a9000001'), user.id
11
+ user = User.new("_id" => BSON::ObjectId("52955cc5f9f6a538a9000001"))
12
+ assert_equal BSON::ObjectId("52955cc5f9f6a538a9000001"), user.id
13
13
  end
14
14
 
15
15
  def test_new_record
@@ -22,7 +22,7 @@ class PersistenceTest < Minidoc::TestCase
22
22
  def test_raises_duplicate_key_where_appropriate
23
23
  mock_collection = mock()
24
24
  User.stubs(:collection).returns(mock_collection)
25
- mock_collection.stubs(:<<).raises(Mongo::OperationFailure.new('Duplicate key exception', Minidoc::DuplicateKey::DUPLICATE_KEY_ERROR_CODE))
25
+ mock_collection.stubs(:<<).raises(Mongo::OperationFailure.new("Duplicate key exception", Minidoc::DuplicateKey::DUPLICATE_KEY_ERROR_CODE))
26
26
 
27
27
  user = User.new
28
28
  assert_raises(Minidoc::DuplicateKey) { user.save }
@@ -72,6 +72,21 @@ class PersistenceTest < Minidoc::TestCase
72
72
  assert_equal "Noah", user.reload.name
73
73
  end
74
74
 
75
+ def test_update_same_collection
76
+ user = User.create(name: "Bryan", age: 20)
77
+ user.name = "Noah"
78
+ assert_equal "Noah", user.name
79
+ user.save
80
+ assert_equal "Noah", user.reload.name
81
+ second_user = SecondUser.find_one(age: 20)
82
+ assert_equal second_user.id, user.id
83
+ second_user.age = 21
84
+ assert_equal 21, second_user.age
85
+ second_user.save
86
+ assert_equal 21, second_user.reload.age
87
+ assert_equal "Noah", user.reload.name
88
+ end
89
+
75
90
  def test_destroy
76
91
  user = User.create(name: "Bryan")
77
92
  assert_equal false, user.destroyed?
@@ -1,6 +1,13 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class QueryTest < Minidoc::TestCase
4
+ def test_all
5
+ User.collection << { name: "Joe" }
6
+ User.collection << { name: "Bryan" }
7
+ users = User.all
8
+ assert_equal %w[Bryan Joe], users.map(&:name).sort
9
+ end
10
+
4
11
  def test_count_all
5
12
  User.collection << { name: "Joe" }
6
13
  User.collection << { name: "Bryan" }
@@ -37,4 +44,21 @@ class QueryTest < Minidoc::TestCase
37
44
  assert_equal user, User.find_one({})
38
45
  assert_equal nil, User.find_one(name: "Noah")
39
46
  end
47
+
48
+ def test_find_one!
49
+ user = User.create(name: "Bryan")
50
+ assert_equal user, User.find_one!(name: "Bryan")
51
+ assert_raises(Minidoc::DocumentNotFoundError) { User.find_one!(name: "Noah") }
52
+ end
53
+
54
+ def test_find_one_or_initialize
55
+ user = User.create(name: "Bryan", age: 1)
56
+ assert user == User.find_one_or_initialize(name: "Bryan")
57
+ assert User.find_one_or_initialize(name: "Noah").is_a?(User)
58
+ assert User.find_one_or_initialize(name: "Noah").new_record?
59
+ user = User.create(name: "Noah", age: 1)
60
+ assert user == User.find_one_or_initialize({ age: 1 }, { sort: { name: -1 } })
61
+ assert_raises(ArgumentError) { User.find_one_or_initialize("foo") }
62
+ end
63
+
40
64
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class ReadOnlyTest < Minidoc::TestCase
4
4
  class ReadOnlyUser < Minidoc::ReadOnly
@@ -1,4 +1,4 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class TimestampsTest < Minidoc::TestCase
4
4
  class User < ::User
@@ -1,4 +1,4 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class UniquenessValidatorTest < Minidoc::TestCase
4
4
  class User < ::User
@@ -1,4 +1,4 @@
1
- require File.expand_path('../helper', __FILE__)
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class ValidationsTest < Minidoc::TestCase
4
4
  class User < ::User
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minidoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Helmkamp
8
+ - Code Climate
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2016-09-28 00:00:00.000000000 Z
12
+ date: 2016-09-29 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activesupport
@@ -17,6 +18,9 @@ dependencies:
17
18
  - - ">="
18
19
  - !ruby/object:Gem::Version
19
20
  version: 3.0.0
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '5'
20
24
  type: :runtime
21
25
  prerelease: false
22
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,6 +28,9 @@ dependencies:
24
28
  - - ">="
25
29
  - !ruby/object:Gem::Version
26
30
  version: 3.0.0
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '5'
27
34
  - !ruby/object:Gem::Dependency
28
35
  name: activemodel
29
36
  requirement: !ruby/object:Gem::Requirement
@@ -31,6 +38,9 @@ dependencies:
31
38
  - - ">="
32
39
  - !ruby/object:Gem::Version
33
40
  version: 3.0.0
41
+ - - "<"
42
+ - !ruby/object:Gem::Version
43
+ version: '5'
34
44
  type: :runtime
35
45
  prerelease: false
36
46
  version_requirements: !ruby/object:Gem::Requirement
@@ -38,11 +48,17 @@ dependencies:
38
48
  - - ">="
39
49
  - !ruby/object:Gem::Version
40
50
  version: 3.0.0
51
+ - - "<"
52
+ - !ruby/object:Gem::Version
53
+ version: '5'
41
54
  - !ruby/object:Gem::Dependency
42
55
  name: virtus
43
56
  requirement: !ruby/object:Gem::Requirement
44
57
  requirements:
45
58
  - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.0'
61
+ - - ">="
46
62
  - !ruby/object:Gem::Version
47
63
  version: 1.0.0
48
64
  type: :runtime
@@ -50,6 +66,9 @@ dependencies:
50
66
  version_requirements: !ruby/object:Gem::Requirement
51
67
  requirements:
52
68
  - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '1.0'
71
+ - - ">="
53
72
  - !ruby/object:Gem::Version
54
73
  version: 1.0.0
55
74
  - !ruby/object:Gem::Dependency
@@ -66,58 +85,21 @@ dependencies:
66
85
  - - "~>"
67
86
  - !ruby/object:Gem::Version
68
87
  version: '1'
69
- - !ruby/object:Gem::Dependency
70
- name: minitest
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: mocha
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rake
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
88
  description:
112
89
  email:
113
90
  - bryan@brynary.com
91
+ - hello@codeclimate.com
114
92
  executables: []
115
93
  extensions: []
116
94
  extra_rdoc_files: []
117
95
  files:
96
+ - ".codeclimate.yml"
118
97
  - ".gitignore"
98
+ - ".rubocop.yml"
119
99
  - ".ruby-version"
120
100
  - ".travis.yml"
101
+ - CHANGELOG.md
102
+ - CODE_OF_CONDUCT.md
121
103
  - Gemfile
122
104
  - LICENSE.txt
123
105
  - README.md
@@ -130,22 +112,22 @@ files:
130
112
  - lib/minidoc/duplicate_key.rb
131
113
  - lib/minidoc/finders.rb
132
114
  - lib/minidoc/grid.rb
133
- - lib/minidoc/indexes.rb
134
115
  - lib/minidoc/read_only.rb
135
116
  - lib/minidoc/record_invalid.rb
136
117
  - lib/minidoc/test_helpers.rb
137
118
  - lib/minidoc/timestamps.rb
138
119
  - lib/minidoc/validations.rb
139
120
  - lib/minidoc/value.rb
121
+ - lib/minidoc/version.rb
140
122
  - minidoc.gemspec
141
123
  - test/activemodel_test.rb
142
124
  - test/belongs_to_test.rb
143
125
  - test/connection_test.rb
144
126
  - test/counters_test.rb
145
127
  - test/duplicate_key_test.rb
128
+ - test/first_run_test.rb
146
129
  - test/grid_test.rb
147
130
  - test/helper.rb
148
- - test/indexes_test.rb
149
131
  - test/locale/en.yml
150
132
  - test/persistence_test.rb
151
133
  - test/query_test.rb
@@ -153,7 +135,7 @@ files:
153
135
  - test/timestamps_test.rb
154
136
  - test/uniqueness_validator_test.rb
155
137
  - test/validations_test.rb
156
- homepage: https://github.com/brynary/minidoc
138
+ homepage: https://github.com/codeclimate/minidoc
157
139
  licenses:
158
140
  - MIT
159
141
  metadata: {}
@@ -168,9 +150,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
150
  version: '0'
169
151
  required_rubygems_version: !ruby/object:Gem::Requirement
170
152
  requirements:
171
- - - ">="
153
+ - - ">"
172
154
  - !ruby/object:Gem::Version
173
- version: '0'
155
+ version: 1.3.1
174
156
  requirements: []
175
157
  rubyforge_project:
176
158
  rubygems_version: 2.5.1
@@ -183,9 +165,9 @@ test_files:
183
165
  - test/connection_test.rb
184
166
  - test/counters_test.rb
185
167
  - test/duplicate_key_test.rb
168
+ - test/first_run_test.rb
186
169
  - test/grid_test.rb
187
170
  - test/helper.rb
188
- - test/indexes_test.rb
189
171
  - test/locale/en.yml
190
172
  - test/persistence_test.rb
191
173
  - test/query_test.rb
@@ -193,4 +175,3 @@ test_files:
193
175
  - test/timestamps_test.rb
194
176
  - test/uniqueness_validator_test.rb
195
177
  - test/validations_test.rb
196
- has_rdoc:
@@ -1,31 +0,0 @@
1
- require "active_support/concern"
2
-
3
- module Minidoc::Indexes
4
- extend ActiveSupport::Concern
5
-
6
- module ClassMethods
7
- MONGO_DUPLICATE_KEY_ERROR_CODE = 11000
8
-
9
- def ensure_index(key_or_keys, options = {})
10
- indexes = Array(key_or_keys).map { |key| { key => 1 } }.reduce(:merge)
11
-
12
- collection.ensure_index(indexes, options)
13
- end
14
-
15
- # Rescue a <tt>Mongo::OperationFailure</tt> exception which originated from
16
- # duplicate key error (error code 11000) in the given block.
17
- #
18
- # Returns the status of the operation in the given block, or +false+ if the
19
- # exception was raised.
20
- def rescue_duplicate_key_errors
21
- yield
22
- rescue Mongo::OperationFailure => exception
23
- if exception.respond_to?(:error_code) &&
24
- exception.error_code == MONGO_DUPLICATE_KEY_ERROR_CODE
25
- return false
26
- else
27
- raise
28
- end
29
- end
30
- end
31
- end
@@ -1,52 +0,0 @@
1
- require File.expand_path('../helper', __FILE__)
2
-
3
- class IndexesTest < Minidoc::TestCase
4
- class Company < Minidoc
5
- self.collection_name = "accounts"
6
-
7
- include Minidoc::Indexes
8
-
9
- attribute :name
10
- attribute :title
11
- attribute :description
12
- end
13
-
14
- def test_ensure_index_single
15
- Company.ensure_index(:name)
16
-
17
- assert_equal %w( name ), indexed_keys(Company, "name_1")
18
- end
19
-
20
- def test_ensure_index_multiple
21
- Company.ensure_index([:name, :title])
22
-
23
- assert_equal %w( name title ), indexed_keys(Company, "name_1_title_1")
24
- end
25
-
26
- def test_ensure_index_options
27
- Company.ensure_index(:name, unique: true)
28
-
29
- assert index_info(Company, "name_1")["unique"]
30
- end
31
-
32
- def test_rescue_duplicate_key_errors_not_raising_exception
33
- Company.ensure_index(:name, unique: true)
34
-
35
- Company.rescue_duplicate_key_errors do
36
- Company.create!(name: "CodeClimate")
37
- Company.create!(name: "CodeClimate")
38
- end
39
- end
40
-
41
- private
42
-
43
- def index_info(klass, name)
44
- klass.collection.index_information[name] || {}
45
- end
46
-
47
- def indexed_keys(klass, name)
48
- key_info = index_info(klass, name)["key"] || {}
49
- key_info.keys
50
- end
51
-
52
- end