- Devise https://github.com/heartcombo/devise
- Rails Admin https://github.com/railsadminteam/rails_admin
- Rails Admin Import https://github.com/stephskardal/rails_admin_import
- CanCanCan https://github.com/CanCanCommunity/cancancan
- Pundit https://github.com/varvet/pundit
# Create new project:
$ rails _7.1.1_ new beaver_lists
$ cd beaver_lists
# Install dependencies
$ bundle install
# Add devise
$ bundle add devise
# Install devise into project
$ rails generate devise:install
# Create devise auth model
$ rails generate devise Admin
In this case I uncomment the trackable fields.
# ...
# Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
# ...
Going to terminal to run the migration
$ rails db:migrate
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
Open the Gemfile in a Editor and remove the sqlite line and include the pg gem line.
# gem "sqlite3", "~> 1.4"
gem 'pg'
#adapter: sqlite3
adapter: postgresql
#...
#database: storage/development.sqlite3
database: beaver_lists_dev
#...
#database: storage/development.sqlite3
database: beaver_lists_test
#...
#database: storage/development.sqlite3
database: beaver_lists_prod
Going to terminal create the batabase in postgres
$ rails db:create
# ...
gem 'rails_admin'
gem 'rails_admin_import'
# ...
group :development do
# ...
gem 'byebug'
gem 'database_cleaner-active_record'
gem 'factory_bot_rails'
gem 'faker'
gem 'rspec-rails'
gem 'rubocop-rails'
gem 'rubocop-rspec'
# gem 'timecop' # For now since we don't have time related business logic we don't add it.
# gem 'vcr' # For now since we don't perform external requests we don't add it.
# gem 'webmock' # For now since we don't perform external requests we don't add it.
end
# ...
Install gems
$ bundle install
require:
- rubocop-rspec
- rubocop-rails
AllCops:
NewCops: enable
# https://batsov.com/articles/2022/01/20/bad-ruby-hash-value-omission/
Style/HashSyntax:
Enabled: false
Add new file at project root .rubocop.yml with
inherit_from:
- config/rubocop.yml
AllCops:
SuggestExtensions: false
Excludes:
- db/schema.rb
- bin/bundle
Style/Documentation:
Enabled: false
Layout/LineLength:
Exclude:
- db/schema.rb
- config/initializers/devise.rb
Metrics/MethodLength:
Exclude:
- db/migrate/*.rb
Metrics/BlockLength:
Exclude:
- config/environments/development.rb
Run rubocop for No offences, with argument -A will autocorrect all existing issues:
$ rubocop -A
[note we want to take advantage of importmaps]
- importmap gem - Make sure on your
Gemfileyou have the referencegem 'importmap-rails' - importmap installed - To install into your project run on the terminal
$ bin/rails importmap:install
Having the pre-requisite run on terminal:
$ rails g rails_admin:install --asset=importmap
After installing the rails_admin notice the red message on the end:
You need to merge "scripts": {
"build:css": "sass ./app/assets/stylesheets/rails_admin.scss:./app/assets/builds/rails_admin.css --no-source-map --load-path=node_modules"
} into the existing scripts in your package.json.
Taking 'build:css' as an example, if you're already have application.sass.css for the sass build, the resulting script would look like:
sass ./app/assets/stylesheets/application.sass.scss:./app/assets/builds/application.css ./app/assets/stylesheets/rails_admin.scss:./app/assets/builds/rails_admin.css --no-source-map --load-path=node_modules
You need to do what is told to do, you need to make sure all your .scss files are listed on the script of the package.json.
By default in a clean install it looks like this:
{
"dependencies": {
"rails_admin": "3.1.2",
"sass": "^1.69.5"
},
"scripts": {
"build:css": "sass ./app/assets/stylesheets/application.sass.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules"
}
}
And it NEEDS to be:
{
"dependencies": {
"rails_admin": "3.1.2",
"sass": "^1.69.5"
},
"scripts": {
"build:css": "sass ./app/assets/stylesheets/application.sass.scss:./app/assets/builds/application.css ./app/assets/stylesheets/rails_admin.scss:./app/assets/builds/rails_admin.css --no-source-map --load-path=node_modules"
}
}
Error title Sprockets::Rails::Helper::AssetNotPrecompiledError in RailsAdmin::Main#dashboard
Error message:
Showing /Users/.../.rvm/gems/ruby-3.2.2/gems/rails_admin-3.1.2/app/views/layouts/rails_admin/_head.html.erb where line #20 raised:
Asset `rails_admin.js` was not declared to be precompiled in production.
Declare links to your assets in `app/assets/config/manifest.js`.
//= link rails_admin.js
and restart your server
Normally this happens when you didn't have importmaps installed, having the importmap gem file you could fix this by just running the command to install it $ bin/rails importmap:install
But in practice since the rails_admin install script did update the project application.css to application.sass.scss already you just need to make sure the folders of those files are on the manifest.js:
The manifest.js should have the following paths and file types:
//= link_tree ../images
//= link_tree ../builds
//= link_tree ../../javascript .js
//= link_tree ../../../vendor/javascript .js
By passing the --asset=importmap to the install command of rails_admin it should have include into the project config/initializers/assets.rb the path of the webfonts files of fontawesome into the Rails application assets paths.
tldh: make sure your assets.rb contains:
# ...
Rails.application.config.assets.paths << Rails.root.join("node_modules/@fortawesome/fontawesome-free/webfonts")
Open config/initializers/rails_admin.rb and uncomment the Devise section. Now when you open the rails_admin route it should check if user is authenticate before presenting the views.
The file should have:
RailsAdmin.config do |config|
# ...
# == Devise ==
config.authenticate_with do
warden.authenticate! scope: :admin
end
config.current_user_method(&:current_admin)
# ...
end
Include gem on Gemfile:
gem "pundit"
Download dependencies
$ bundle install
Run the install command from Pundit to automatically create the default configuration:
$ rails g pundit:install
Uncomment the Pundit line from the .../config/initializers/rails_admin.rb
# ...
# == Pundit ==
config.authorize_with :pundit
# ...
Since we are using a model different than 'user' Pundit will fail to retrieve the current admin logged in failing all the authorizations. To solve this create a new controller for rails_admin and override the pundit_user to the correct one.
# .../app/controllers/admin/base_controller.rb
# frozen_string_literal: true
class Admin::BaseController < ApplicationController
include Pundit
# This will tell pundit which method returns the logged person.
def pundit_user
current_admin
end
end
Then get back to the .../config/initializers/rails_admin.rb and add the parent_controller:
# .../config/initializers/rails_admin.rb
RailsAdmin.config do |config|
# ...
config.parent_controller = "Admin::BaseController"
# ...
A common issue you may get with pundit is the non implemented resolve of the Scode class on .../app/policies/application_policy.rb. To solve this you can just return the scope variable of the resolve.
Change this:
class ApplicationPolicy
# ...
def resolve
raise NotImplementedError, "You must define #resolve in #{self.class}"
end
# ...
end
to this:
class ApplicationPolicy
# ...
def resolve
scope
end
# ...
end
Then you need to add the rails_admin method to it:
# frozen_string_literal: true
class ApplicationPolicy
# ...
def dashboard?
true
end
def export?
true
end
def history?
true
end
def show_in_app?
true
end
end
Links uteis neste topico: https://blog.saeloun.com/2022/01/05/how-to-use-enums-in-rails/ https://dev.to/collinjilbert/basic-enum-usage-for-defining-roles-or-statuses-on-models-in-rails-3c2f
Create a new migration for the admin model:
$ rails generate migration AddRoleToAdmins role:integer
- Não consegui entender se é possível definir um valor default no comando.
Now on your Admin model class include:
class Admin < ApplicationRecord
# ...
enum :role, { admin: 0, editor: 1 }
# ...
end
Links úteis neste topico: https://medium.com/@sustiono19/how-to-manage-authorization-using-pundit-gem-on-ruby-on-rails-69e119ebb256
Use the following command to quickly add policies for a model:
$ rails g pundit:policy admin
And repeat for each model you need. Then update the file according to their actions: For example:
# frozen_string_literal: true
class AdminPolicy < ApplicationPolicy
def index?
user.admin?
end
def show?
user.admin?
end
def edit?
user.admin?
end
def create?
user.admin?
end
end
If you attempt to navigate into some table you don’t have authorisation it will raise an exception.
To fix this, edit your app\controllers\admin\base_controller.rb to have:
class Admin::BaseController < ApplicationController
include Pundit
# ...
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
private
def user_not_authorized
flash[:alert] = 'You are not authorized to perform this action.'
redirect_to dashboard_path
end
end
Links úteis: https://github.com/stephskardal/rails_admin_import
Add the gem to your Gemfile:
# ...
gem 'rails_admin_import'
# ...
Then edit your config/initializers/rails_admin.rb to include import on the available actions.
And since in our case we also need to track each document uploaded we will set true to config.pass_filename which will make the filename available through record[:filename_importer] parameter when importing.
RailsAdmin.config do |config|
# ...
config.actions do
dashboard # mandatory
index # mandatory
new
export
bulk_delete
show
edit
delete
show_in_app
import # The new field we need
end
config.configure_with(:import) do |config|
config.pass_filename = true # To make the filename available when importing.
end
end
Then we need to update the Pundit files to have this new reference. I mean on the application_policy.rb and all the respective model policy classes.
class ApplicationPolicy
# ...
def import?
true
end
end
class AdminPolicy < ApplicationPolicy
# ...
def import?
false
end
end
Links úteis: https://www.appsloveworld.com/ruby/100/307/assign-value-to-rails-admin-list-field
Go to your config\initializers\rails_admin.rb and add the model you need to adjust. example:
RailsAdmin.config do |config|
# ...
config.model Freelancer do
edit do
field :name do
required true
end
field :email do
required true
end
field :start_date do
required true
end
include_all_fields
end
end
end
Need table with Leads, Documents, Freelancers, Reports
-
Creating a Rails App to upload CSV Using Rails Admin, Admin Import and Devise
-
devise_rails_admin_can_can_can_example
-
Pundit with Rails plus User, Admin and Roles Models
-
varvet/pundit
-
Using devise for multiple models
-
How to Setup Multiple Devise User Models
-
Different Devise configurations for each model
-
[Devise repo] Configuring multiple models
-
railsadminteam/rails_admin - Wiki
-
Using RailsAdmin with Pundit
-
How to manage Authorization using Pundit gem on Ruby on Rails
- Hotwire
- thoughtbot signature on open source repositories
- How to Run a Rails App in Production Locally
- How to Migrate a Rails 6 App From sass-rails to cssbundling-rails
- Rails 7, Bootstrap 5 and importmaps without nodejs
- How to use Import Maps in Rails 7 (with examples)
- Import Maps Under the Hood in Rails 7