Skip to content

Commit f64da3a

Browse files
committed
Add missing ORM specs and fix bugs discovered
1 parent 9f55885 commit f64da3a

31 files changed

+629
-319
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848
if: matrix.ruby == '2.7' && github.event_name != 'pull_request'
4949
continue-on-error: ${{ matrix.allow_failures != 'false' }}
5050
- name: Run tests
51-
run: bundle exec rake test
51+
run: bundle exec rake
5252
- name: CodeClimate Post-build Notification
5353
run: cc-test-reporter after-build
5454
if: matrix.ruby == '2.7' && github.event_name != 'pull_request' && always()

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
/pkg/
1212
/spec/reports/
1313
/tmp/
14+
/rethinkdb_data
1415

1516
*.gem
1617

.simplecov

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# frozen_string_literal: true
22

33
SimpleCov.start do
4+
add_filter '/.github/'
5+
add_filter '/coverage/'
6+
add_filter '/rethinkdb_data/'
47
add_filter '/spec/'
8+
add_filter '/spec_orms/'
59
add_filter '/vendor/bundle/'
610
end

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
## [Unreleased]
1010

11+
## [3.0.7] - 2021-03-23
12+
13+
### Fixed
14+
15+
- \[ActiveRecord\] Fixed [#110](https://github.com/omniauth/omniauth-identity/issues/110) which prevented `OmniAuth::Identity::Models::ActiveRecord`-based records from saving.
16+
- \[CouchPotato\] Fixed `OmniAuth::Identity::Models::CouchPotato`'s `#save`.
17+
- \[Sequel\] Fixed `OmniAuth::Identity::Models::Sequel`'s `#save`.
18+
- \[Model\] Only define `::create`, `#save`, and `#persisted?` when not already defined.
19+
- \[Model\] Restore original `info` functionality which set `name` based on `first_name`, `last_name`, or `nickname`
20+
21+
### Changed
22+
23+
- Upgraded to a newer `OmniAuth::Identity::SecurePassword` ripped from [Rails 6-1-stable](https://github.com/rails/rails/blob/6-1-stable/activemodel/lib/active_model/secure_password.rb)
24+
- Aeons ago the original was ripped from Rails 3.1, and frozen in time.
25+
While writing specs, it was discovered to be incompatible with this gems' Sequel adapter.
26+
- Specs validate that the new version does work.
27+
In any case, the ripped version is only used when the `has_secure_password` macro is not yet defined in the class.
28+
29+
### Added
30+
31+
- New specs to cover real use cases and implementations of each ORM model adapter that ships with the gem:
32+
- ActiveRecord (Polyglot - Many Relational Databases)
33+
- Sequel (Polyglot - Many Relational Databases)
34+
- CouchPotato (CouchDB)
35+
- Mongoid (MongoDB)
36+
- NoBrainer (RethinkDB)
37+
1138
## [3.0.6] - 2021-03-20
1239

1340
### Fixed

Gemfile

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,18 @@ group :documentation do
1717
end
1818

1919
group :development, :test do
20+
# ORMs
2021
if ruby_version < Gem::Version.new('2.5.0')
21-
gem 'activerecord', '~> 5' # rails 5 works with Ruby 2.4
22+
gem 'activerecord', '~> 5', require: false # rails 5 works with Ruby 2.4
2223
else
23-
gem 'activerecord', '~> 6' # rails 6 requires Ruby 2.5 or later
24+
gem 'activerecord', '~> 6', require: false # rails 6 requires Ruby 2.5 or later
2425
end
26+
gem 'anonymous_active_record', '~> 1', require: false
27+
gem 'mongoid', '~> 7', require: false
28+
gem 'nobrainer', '~> 0', require: false
29+
gem 'sequel', '~> 5', require: false
30+
gem 'couch_potato', github: 'langalex/couch_potato', require: false
31+
gem 'mongoid-rspec', github: 'mongoid/mongoid-rspec', require: false
2532

2633
if ruby_version >= Gem::Version.new('2.4')
2734
# No need to run byebug / pry on earlier versions
@@ -44,12 +51,10 @@ group :development, :test do
4451
gem 'simplecov', '~> 0.21', platform: :mri
4552
end
4653

47-
gem 'couch_potato', github: 'langalex/couch_potato'
4854
gem 'growl'
4955
gem 'guard'
5056
gem 'guard-bundler'
5157
gem 'guard-rspec'
52-
gem 'mongoid-rspec', github: 'mongoid/mongoid-rspec'
5358
gem 'rb-fsevent'
5459
end
5560

README.md

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ Just include `OmniAuth::Identity::Models::Sequel` mixin, and specify
9393
whatever else you will need.
9494

9595
```ruby
96-
class SequelTestIdentity < Sequel::Model
97-
include OmniAuth::Identity::Models::Sequel
96+
class SequelTestIdentity < Sequel::Model(:identities)
97+
include ::OmniAuth::Identity::Models::Sequel
9898
auth_key :email
9999
# whatever else you want!
100100
end
@@ -108,8 +108,8 @@ fields that you will need.
108108

109109
```ruby
110110
class Identity
111-
include Mongoid::Document
112-
include OmniAuth::Identity::Models::Mongoid
111+
include ::Mongoid::Document
112+
include ::OmniAuth::Identity::Models::Mongoid
113113

114114
field :email, type: String
115115
field :name, type: String
@@ -124,8 +124,9 @@ fields that you will need.
124124

125125
```ruby
126126
class Identity
127-
include CouchPotato::Persistence
128-
include OmniAuth::Identity::Models::CouchPotatoModule
127+
# NOTE: CouchPotato::Persistence must be included before OmniAuth::Identity::Models::CouchPotatoModule
128+
include ::CouchPotato::Persistence
129+
include ::OmniAuth::Identity::Models::CouchPotatoModule
129130

130131
property :email
131132
property :password_digest
@@ -147,8 +148,8 @@ fields that you will need.
147148

148149
```ruby
149150
class Identity
150-
include NoBrainer::Document
151-
include OmniAuth::Identity::Models::NoBrainer
151+
include ::NoBrainer::Document
152+
include ::OmniAuth::Identity::Models::NoBrainer
152153

153154
auth_key :email
154155
end
@@ -265,6 +266,35 @@ option :locate_conditions, ->(req) { { model.auth_key => req['auth_key'] } }
265266

266267
Please contribute some documentation if you have the gumption! The maintainer's time is limited, and sometimes the authors of PRs with new options don't update the _this_ readme. 😭
267268

269+
## Contributing
270+
271+
1. Fork it
272+
2. Create your feature branch (`git checkout -b my-new-feature`)
273+
3. Commit your changes (`git commit -am ‘Added some feature’`)
274+
4. Push to the branch (`git push origin my-new-feature`)
275+
5. Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.
276+
- NOTE: In order to run *all* the tests you will need to have the following databases installed and configured.
277+
1. [RethinkDB](https://rethinkdb.com), an open source, real-time, web database, [installed](https://rethinkdb.com/docs/install/) and [running](https://rethinkdb.com/docs/start-a-server/), e.g.
278+
```bash
279+
brew install rethinkdb
280+
rethinkdb
281+
```
282+
2. [MongoDB](https://docs.mongodb.com/manual/administration/install-community/)
283+
```bash
284+
brew tap mongodb/brew
285+
brew install [email protected]
286+
287+
```
288+
To skip the RethinkDB-based, NoBrainer (ORM), tests run:
289+
```bash
290+
bundle exec rspec spec --tag '~nobrainer'
291+
```
292+
Or if you have RethinkDB setup, then run all:
293+
```bash
294+
bundle exec rspec spec
295+
```
296+
6. Create new Pull Request
297+
268298
## License
269299

270300
MIT License. See LICENSE for details.

Rakefile

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,17 @@ require 'bundler/gem_tasks'
44

55
begin
66
require 'rspec/core/rake_task'
7-
RSpec::Core::RakeTask.new(:spec)
7+
primary = RSpec::Core::RakeTask.new(:spec)
8+
active_record = RSpec::Core::RakeTask.new(:spec_orm_active_record)
9+
active_record.pattern = "spec_orms/active_record_spec.rb"
10+
couch_potato = RSpec::Core::RakeTask.new(:spec_orm_couch_potato)
11+
couch_potato.pattern = "spec_orms/couch_potato_spec.rb"
12+
mongoid = RSpec::Core::RakeTask.new(:spec_orm_mongoid)
13+
mongoid.pattern = "spec_orms/mongoid_spec.rb"
14+
no_brainer = RSpec::Core::RakeTask.new(:spec_orm_no_brainer)
15+
no_brainer.pattern = "spec_orms/no_brainer_spec.rb"
16+
sequel = RSpec::Core::RakeTask.new(:spec_orm_sequel)
17+
sequel.pattern = "spec_orms/sequel_spec.rb"
818
rescue LoadError
919
task :spec do
1020
warn 'RSpec is disabled'
@@ -21,4 +31,11 @@ rescue LoadError
2131
end
2232
end
2333

24-
task default: [:test]
34+
task default: [
35+
:test,
36+
:spec_orm_active_record,
37+
:spec_orm_couch_potato,
38+
:spec_orm_mongoid,
39+
:spec_orm_no_brainer,
40+
:spec_orm_sequel
41+
]

lib/omniauth/identity/model.rb

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ module Model
2525

2626
def self.included(base)
2727
base.extend ClassMethods
28+
base.extend ClassCreateApi unless base.respond_to?(:create)
29+
im = base.instance_methods
30+
base.include InstanceSaveApi unless im.include?(:save)
31+
base.include InstancePersistedApi unless im.include?(:persisted?)
2832
end
2933

3034
module ClassMethods
31-
extend Gem::Deprecate
32-
3335
# Authenticate a user with the given key and password.
3436
#
3537
# @param [String] key The unique login key provided for a given identity.
@@ -52,52 +54,56 @@ def auth_key(method = false)
5254
@auth_key || 'email'
5355
end
5456

57+
58+
# Locate an identity given its unique login key.
59+
#
60+
# @abstract
61+
# @param [String] key The unique login key.
62+
# @return [Model] An instance of the identity model class.
63+
def locate(_key)
64+
raise NotImplementedError
65+
end
66+
end
67+
68+
module ClassCreateApi
5569
# Persists a new Identity object to the ORM.
56-
# Defaults to calling super. Override as needed per ORM.
70+
# Only included if the class doesn't define create, as a reminder to define create.
71+
# Override as needed per ORM.
5772
#
5873
# @deprecated v4.0 will begin using {#new} with {#save} instead.
5974
# @abstract
6075
# @param [Hash] args Attributes of the new instance.
6176
# @return [Model] An instance of the identity model class.
6277
# @since 3.0.5
63-
def create(*args)
64-
raise NotImplementedError unless defined?(super)
65-
66-
super
78+
def create(*_args)
79+
raise NotImplementedError
6780
end
81+
end
6882

69-
# Locate an identity given its unique login key.
83+
module InstanceSaveApi
84+
# Persists a new Identity object to the ORM.
85+
# Default raises an error. Override as needed per ORM.
86+
# This base version's arguments are modeled after ActiveModel
87+
# since it is a pattern many ORMs follow
7088
#
7189
# @abstract
72-
# @param [String] key The unique login key.
7390
# @return [Model] An instance of the identity model class.
74-
def locate(key)
91+
# @since 3.0.5
92+
def save(**_options, &_block)
7593
raise NotImplementedError
7694
end
7795
end
7896

79-
# Persists a new Identity object to the ORM.
80-
# Default raises an error. Override as needed per ORM.
81-
#
82-
# @abstract
83-
# @return [Model] An instance of the identity model class.
84-
# @since 3.0.5
85-
def save
86-
raise NotImplementedError unless defined?(super)
87-
88-
super
89-
end
90-
91-
# Checks if the Identity object is persisted in the ORM.
92-
# Defaults to calling super. Override as needed per ORM.
93-
#
94-
# @abstract
95-
# @return [true or false] true if object exists, false if not.
96-
# @since 3.0.5
97-
def persisted?
98-
raise NotImplementedError unless defined?(super)
99-
100-
super
97+
module InstancePersistedApi
98+
# Checks if the Identity object is persisted in the ORM.
99+
# Default raises an error. Override as needed per ORM.
100+
#
101+
# @abstract
102+
# @return [true or false] true if object exists, false if not.
103+
# @since 3.0.5
104+
def persisted?
105+
raise NotImplementedError
106+
end
101107
end
102108

103109
# Returns self if the provided password is correct, false
@@ -106,7 +112,7 @@ def persisted?
106112
# @abstract
107113
# @param [String] password The password to check.
108114
# @return [self or false] Self if authenticated, false if not.
109-
def authenticate(password)
115+
def authenticate(_password)
110116
raise NotImplementedError
111117
end
112118

@@ -163,9 +169,13 @@ def auth_key=(value)
163169
#
164170
# @return [Hash] A string-keyed hash of user information.
165171
def info
166-
SCHEMA_ATTRIBUTES.each_with_object({}) do |attribute, hash|
172+
info = {}
173+
SCHEMA_ATTRIBUTES.each_with_object(info) do |attribute, hash|
167174
hash[attribute] = send(attribute) if respond_to?(attribute)
168175
end
176+
info['name'] ||= [info['first_name'], info['last_name']].join(' ').strip if info['first_name'] || info['last_name']
177+
info['name'] ||= info['nickname']
178+
info
169179
end
170180
end
171181
end

lib/omniauth/identity/models/active_record.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ module OmniAuth
66
module Identity
77
module Models
88
class ActiveRecord < ::ActiveRecord::Base
9-
include OmniAuth::Identity::Model
10-
include OmniAuth::Identity::SecurePassword
9+
include ::OmniAuth::Identity::Model
10+
include ::OmniAuth::Identity::SecurePassword
1111

1212
self.abstract_class = true
1313
has_secure_password

lib/omniauth/identity/models/couch_potato.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module Identity
77
module Models
88
# can not be named CouchPotato since there is a class with that name
99
# NOTE: CouchPotato is based on ActiveModel.
10+
# NOTE: CouchPotato::Persistence must be included before OmniAuth::Identity::Models::CouchPotatoModule
1011
module CouchPotatoModule
1112
def self.included(base)
1213
base.class_eval do
@@ -23,6 +24,10 @@ def self.auth_key=(key)
2324
def self.locate(search_hash)
2425
where(search_hash).first
2526
end
27+
28+
def save
29+
CouchPotato.database.save(self)
30+
end
2631
end
2732
end
2833
end

0 commit comments

Comments
 (0)