pollett 0.1.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +81 -0
- data/Rakefile +25 -0
- data/app/controllers/concerns/pollett/controller.rb +37 -0
- data/app/controllers/pollett/application_controller.rb +4 -0
- data/app/controllers/pollett/keys_controller.rb +5 -0
- data/app/controllers/pollett/sessions_controller.rb +5 -0
- data/app/controllers/pollett/users_controller.rb +5 -0
- data/app/mailers/pollett/mailer.rb +5 -0
- data/app/models/concerns/pollett/user.rb +40 -0
- data/app/models/pollett/context.rb +5 -0
- data/app/models/pollett/key.rb +5 -0
- data/app/models/pollett/session.rb +5 -0
- data/app/serializers/pollett/key_serializer.rb +5 -0
- data/app/serializers/pollett/session_serializer.rb +5 -0
- data/app/serializers/user_serializer.rb +3 -0
- data/app/services/pollett/authenticate_user.rb +5 -0
- data/app/services/pollett/change_password.rb +5 -0
- data/app/services/pollett/create_session.rb +5 -0
- data/app/services/pollett/register_user.rb +5 -0
- data/app/services/pollett/reset_password.rb +5 -0
- data/app/views/pollett/mailer/reset.text.erb +5 -0
- data/app/views/pollett/mailer/welcome.text.erb +1 -0
- data/config/locales/en.yml +14 -0
- data/config/routes.rb +11 -0
- data/db/migrate/20150226024506_create_pollett_contexts.rb +21 -0
- data/lib/generators/pollett/install/install_generator.rb +123 -0
- data/lib/generators/pollett/install/templates/db/migrate/add_pollett_to_users.rb +21 -0
- data/lib/generators/pollett/install/templates/db/migrate/create_users.rb +15 -0
- data/lib/generators/pollett/install/templates/initializer.rb +3 -0
- data/lib/generators/pollett/install/templates/user.rb +3 -0
- data/lib/pollett.rb +20 -0
- data/lib/pollett/concerns.rb +5 -0
- data/lib/pollett/concerns/controllers.rb +3 -0
- data/lib/pollett/concerns/controllers/keys_controller.rb +37 -0
- data/lib/pollett/concerns/controllers/sessions_controller.rb +43 -0
- data/lib/pollett/concerns/controllers/users_controller.rb +28 -0
- data/lib/pollett/concerns/mailers.rb +1 -0
- data/lib/pollett/concerns/mailers/mailer.rb +24 -0
- data/lib/pollett/concerns/models.rb +3 -0
- data/lib/pollett/concerns/models/context.rb +42 -0
- data/lib/pollett/concerns/models/key.rb +13 -0
- data/lib/pollett/concerns/models/session.rb +20 -0
- data/lib/pollett/concerns/serializers.rb +2 -0
- data/lib/pollett/concerns/serializers/context_serializer.rb +21 -0
- data/lib/pollett/concerns/serializers/user_serializer.rb +16 -0
- data/lib/pollett/concerns/services.rb +5 -0
- data/lib/pollett/concerns/services/authenticate_user.rb +21 -0
- data/lib/pollett/concerns/services/change_password.rb +21 -0
- data/lib/pollett/concerns/services/create_session.rb +27 -0
- data/lib/pollett/concerns/services/register_user.rb +29 -0
- data/lib/pollett/concerns/services/reset_password.rb +27 -0
- data/lib/pollett/configuration.rb +34 -0
- data/lib/pollett/engine.rb +12 -0
- data/lib/pollett/rspec.rb +6 -0
- data/lib/pollett/testing/request_helper.rb +106 -0
- data/lib/pollett/version.rb +3 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +12 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy/app/models/user.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/layouts/mailer.text.erb +6 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +32 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +85 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/active_model_serializers.rb +1 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/migrate/20150226030314_enable_uuid_extension.rb +5 -0
- data/spec/dummy/db/migrate/20150226030315_create_users.rb +15 -0
- data/spec/dummy/db/migrate/20150226030316_create_pollett_contexts.pollett.rb +22 -0
- data/spec/dummy/db/schema.rb +49 -0
- data/spec/dummy/log/development.log +1315 -0
- data/spec/dummy/log/test.log +181283 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/pollett_context.rb +5 -0
- data/spec/factories/pollett_key.rb +5 -0
- data/spec/factories/pollett_session.rb +5 -0
- data/spec/factories/user.rb +7 -0
- data/spec/mailers/pollett/mailer_spec.rb +73 -0
- data/spec/rails_helper.rb +19 -0
- data/spec/requests/keys_spec.rb +67 -0
- data/spec/requests/sessions_spec.rb +176 -0
- data/spec/requests/user_spec.rb +41 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/email_helper.rb +9 -0
- metadata +323 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0b840bb4badc9859eb7fda1c68585d2deb6b3de4
|
4
|
+
data.tar.gz: ca1179661479d54174900d8af6181f78d3a31b2a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0680f8f973d73b0b09ab6e3d463a2e3b5f975dd44f69a23eaf114ad1d65c30f3d818d1da46d17040d34d631fcc9eb3b303d63a40d598efb92385937db2299a3d
|
7
|
+
data.tar.gz: 4e7e6e4c1e72cdb5e0d9c903554831a1e52b7a05a31cecfa9cd2b33e27c2b521fc9f412be3bc59794e8f290ac4790e938c488d49302b08eba218ed9fa3cb5c7f
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 Jason Kriss
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# Pollett
|
2
|
+
|
3
|
+
Token-based authentication for your Rails API.
|
4
|
+
|
5
|
+
Pollett is a simple authentication library for your API-only Rails app. It treats sessions as a [first class domain concern]
|
6
|
+
(https://github.com/blog/1661-modeling-your-app-s-user-session) and takes its inspiration from [Clearance](https://github.com/thoughtbot/clearance).
|
7
|
+
|
8
|
+
Pollett currently requires Postgres and the use of UUID primary keys. This means you will need to have the `uuid-ossp` extension enabled before using Pollett.
|
9
|
+
|
10
|
+
## Install
|
11
|
+
|
12
|
+
To get started, add Pollett to your `Gemfile`, `bundle install`, and run the
|
13
|
+
`install generator`:
|
14
|
+
|
15
|
+
```sh
|
16
|
+
$ rails g pollett:install
|
17
|
+
```
|
18
|
+
|
19
|
+
The generator:
|
20
|
+
|
21
|
+
* Inserts `Pollett::User` into your `User` model
|
22
|
+
* Inserts `Pollett::Controller` into your `ApplicationController`
|
23
|
+
* Creates an initializer to allow further configuration
|
24
|
+
* Creates a migration that either creates a users table or adds the necessary columns to the existing table
|
25
|
+
* Copies over the Session model migration
|
26
|
+
* Mounts the engine
|
27
|
+
|
28
|
+
Then, just migrate the database:
|
29
|
+
|
30
|
+
```sh
|
31
|
+
$ rake db:migrate
|
32
|
+
```
|
33
|
+
|
34
|
+
Finally, you must implement the `render_list` method in your `ApplicationController`. Use this method to paginate a list of records any way you want.
|
35
|
+
|
36
|
+
## Configure
|
37
|
+
|
38
|
+
Override any of these defaults in `config/initializers/pollett.rb`:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
Pollett.configure do |config|
|
42
|
+
config.user_model = ::User
|
43
|
+
config.minimum_password_length = 8
|
44
|
+
config.send_welcome_email = true
|
45
|
+
config.parent_mailer = ::ApplicationMailer
|
46
|
+
config.from_email = "noreply@example.com"
|
47
|
+
config.reset_url = ->(token) { "https://example.com/#{token}/reset" }
|
48
|
+
config.whitelist = []
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
At minimum, you will need to configure `reset_url` so that the link will be correct in password reset emails. Also, if a default "from" email is not set in your `parent_mailer`, you will need to configure `from_email` as well.
|
53
|
+
|
54
|
+
## Use
|
55
|
+
|
56
|
+
### Access Control
|
57
|
+
|
58
|
+
Pollett authentication is opt-out rather than opt-in. This means that if there is an action that does not require authentication, you will need to use `skip_authentication`:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class ArticlesController < ApplicationController
|
62
|
+
skip_authentication only: :safe_action
|
63
|
+
|
64
|
+
def safe_action
|
65
|
+
# something that does not require authentication
|
66
|
+
end
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
As you'd expect, `current_user` can be used from within controllers to access the authenticated user.
|
71
|
+
|
72
|
+
When authentication fails, Pollett raises a `Pollett::Unauthorized` error. You should [rescue_from](http://guides.rubyonrails.org/action_controller_overview.html#rescue-from) this to customize what is rendered.
|
73
|
+
|
74
|
+
### Email
|
75
|
+
Pollett is capable of sending two types of emails. In addition to the standard password reset email, it will send a welcome email upon registration unless `config.send_welcome_email` is set to `false`.
|
76
|
+
|
77
|
+
These emails will make use of whatever `layout` you have specified in your `ApplicationMailer`. If you need to customize the subject of these emails or make minor tweaks to the messages, you can simply override them via [i18n translations]
|
78
|
+
(http://guides.rubyonrails.org/i18n.html). See [config/locales/en.yml](/config/locales/en.yml) for the
|
79
|
+
default behavior.
|
80
|
+
|
81
|
+
If you need to make more elaborate changes, you'll want to override the actual views. See [app/views/pollett/mailer](/app/views/pollett/mailer) for the default behavior.
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Pollett'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
14
|
+
end
|
15
|
+
|
16
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
17
|
+
load 'rails/tasks/engine.rake'
|
18
|
+
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
Bundler::GemHelper.install_tasks
|
25
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Pollett
|
2
|
+
module Controller
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
include ActionController::HttpAuthentication::Token::ControllerMethods
|
6
|
+
|
7
|
+
included do
|
8
|
+
attr_accessor :current_context
|
9
|
+
|
10
|
+
before_action :authenticate!
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def skip_authentication(options = {})
|
15
|
+
skip_before_action(:authenticate!, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def activate_context(context)
|
21
|
+
context.access(request)
|
22
|
+
self.current_context = context
|
23
|
+
end
|
24
|
+
|
25
|
+
def current_user
|
26
|
+
current_context.try(:user)
|
27
|
+
end
|
28
|
+
|
29
|
+
def authenticate!
|
30
|
+
if context = authenticate_with_http_token { |id, _| Context.authenticate(id) }
|
31
|
+
activate_context(context)
|
32
|
+
else
|
33
|
+
raise Unauthorized
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "email_validator"
|
2
|
+
|
3
|
+
module Pollett
|
4
|
+
module User
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
has_secure_password
|
9
|
+
|
10
|
+
has_many :contexts, class_name: "Pollett::Context"
|
11
|
+
has_many :sessions, class_name: "Pollett::Session"
|
12
|
+
has_many :keys, class_name: "Pollett::Key"
|
13
|
+
|
14
|
+
before_validation :normalize_email
|
15
|
+
|
16
|
+
validates :name, presence: true
|
17
|
+
|
18
|
+
validates :email, presence: true,
|
19
|
+
uniqueness: true,
|
20
|
+
email: { strict_mode: true }
|
21
|
+
|
22
|
+
validates :password, length: { minimum: Pollett.config.minimum_password_length }, if: :password
|
23
|
+
end
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
def find_by_normalized_email(email)
|
27
|
+
find_by(email: normalize_email(email))
|
28
|
+
end
|
29
|
+
|
30
|
+
def normalize_email(email)
|
31
|
+
email.to_s.downcase.gsub(/\s+/, "")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def normalize_email
|
37
|
+
self.email = self.class.normalize_email(email)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= t(".body") %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
en:
|
2
|
+
pollett:
|
3
|
+
mailer:
|
4
|
+
welcome:
|
5
|
+
subject: "Welcome!"
|
6
|
+
body: "Welcome aboard!"
|
7
|
+
reset:
|
8
|
+
subject: "Password Reset"
|
9
|
+
opening: "Someone recently requested a password change for your account. To reset your password, just follow this link:"
|
10
|
+
closing: "If you did not make this request, just ignore this email. Your password will remain unchanged."
|
11
|
+
activerecord:
|
12
|
+
attributes:
|
13
|
+
user:
|
14
|
+
password_digest: "Password"
|
data/config/routes.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Pollett::Engine.routes.draw do
|
2
|
+
scope shallow: true, format: false do
|
3
|
+
resource :user, only: [:show, :update, :destroy]
|
4
|
+
|
5
|
+
resources :sessions, except: [:new, :edit, :update] do
|
6
|
+
post :forgot, on: :collection
|
7
|
+
end
|
8
|
+
|
9
|
+
resources :keys, except: [:new, :edit, :update]
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreatePollettContexts < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :pollett_contexts, id: :uuid do |t|
|
4
|
+
t.string :type, null: false
|
5
|
+
t.uuid :user_id, null: false
|
6
|
+
t.string :client, null: false
|
7
|
+
t.datetime :revoked_at
|
8
|
+
t.datetime :accessed_at
|
9
|
+
t.string :ip
|
10
|
+
t.string :user_agent
|
11
|
+
|
12
|
+
t.timestamps null: false
|
13
|
+
end
|
14
|
+
|
15
|
+
add_foreign_key :pollett_contexts, :users, on_delete: :cascade
|
16
|
+
|
17
|
+
add_index :pollett_contexts, :user_id
|
18
|
+
add_index :pollett_contexts, :accessed_at
|
19
|
+
add_index :pollett_contexts, :revoked_at
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require "rails/generators/base"
|
2
|
+
require "rails/generators/active_record"
|
3
|
+
|
4
|
+
module Pollett
|
5
|
+
module Generators
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
|
9
|
+
source_root File.expand_path("../templates", __FILE__)
|
10
|
+
|
11
|
+
def mount
|
12
|
+
inject_into_file "config/routes.rb", after: "Rails.application.routes.draw do\n" do
|
13
|
+
" mount Pollett::Engine => \"/\"\n\n"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_initializer
|
18
|
+
copy_file "initializer.rb", "config/initializers/pollett.rb"
|
19
|
+
end
|
20
|
+
|
21
|
+
def inject_into_application_controller
|
22
|
+
inject_into_class "app/controllers/application_controller.rb", ApplicationController do
|
23
|
+
" include Pollett::Controller\n"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_or_inject_into_user_model
|
28
|
+
if File.exist? "app/models/user.rb"
|
29
|
+
inject_into_file "app/models/user.rb", after: "class User < ActiveRecord::Base\n" do
|
30
|
+
" include Pollett::User\n\n"
|
31
|
+
end
|
32
|
+
else
|
33
|
+
copy_file "user.rb", "app/models/user.rb"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_users_migration
|
38
|
+
if users_table_exists?
|
39
|
+
create_add_columns_migration
|
40
|
+
else
|
41
|
+
copy_migration "create_users.rb"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def install_migrations
|
46
|
+
Dir.chdir(Rails.root) { `rake pollett:install:migrations` }
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def users_table_exists?
|
51
|
+
ActiveRecord::Base.connection.table_exists?(:users)
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_add_columns_migration
|
55
|
+
if migration_needed?
|
56
|
+
config = {
|
57
|
+
new_columns: new_columns,
|
58
|
+
new_indexes: new_indexes
|
59
|
+
}
|
60
|
+
|
61
|
+
copy_migration("add_pollett_to_users.rb", config)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def migration_needed?
|
66
|
+
new_columns.any? || new_indexes.any?
|
67
|
+
end
|
68
|
+
|
69
|
+
def new_columns
|
70
|
+
@new_columns ||= {
|
71
|
+
email: "t.string :name, null: false",
|
72
|
+
email: "t.string :email, null: false",
|
73
|
+
password_digest: "t.string :password_digest, null: false",
|
74
|
+
reset_token: "t.string :reset_token"
|
75
|
+
}.reject { |column| existing_users_columns.include?(column.to_s) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def new_indexes
|
79
|
+
@new_indexes ||= {
|
80
|
+
index_users_on_email: "add_index :users, :email, unique: true",
|
81
|
+
index_users_on_reset_token: "add_index :users, :reset_token, unique: true"
|
82
|
+
}.reject { |index| existing_users_indexes.include?(index.to_s) }
|
83
|
+
end
|
84
|
+
|
85
|
+
def copy_migration(migration_name, config = {})
|
86
|
+
unless migration_exists?(migration_name)
|
87
|
+
migration_template(
|
88
|
+
"db/migrate/#{migration_name}",
|
89
|
+
"db/migrate/#{migration_name}",
|
90
|
+
config
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def migration_exists?(name)
|
96
|
+
existing_migrations.include?(name)
|
97
|
+
end
|
98
|
+
|
99
|
+
def existing_migrations
|
100
|
+
@existing_migrations ||= Dir.glob("db/migrate/*.rb").map do |file|
|
101
|
+
migration_name_without_timestamp(file)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def migration_name_without_timestamp(name)
|
106
|
+
name.sub(%r{^.*(db/migrate/)(?:\d+_)?}, "")
|
107
|
+
end
|
108
|
+
|
109
|
+
def existing_users_columns
|
110
|
+
ActiveRecord::Base.connection.columns(:users).map(&:name)
|
111
|
+
end
|
112
|
+
|
113
|
+
def existing_users_indexes
|
114
|
+
ActiveRecord::Base.connection.indexes(:users).map(&:name)
|
115
|
+
end
|
116
|
+
|
117
|
+
# for generating a timestamp when using `create_migration`
|
118
|
+
def self.next_migration_number(dir)
|
119
|
+
ActiveRecord::Generators::Base.next_migration_number(dir)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|