Extract some useful code from January of 2023 app

This commit is contained in:
Eugene Burmakin 2023-02-01 14:30:09 +01:00
parent b648784e88
commit 9bfc268109
9 changed files with 197 additions and 43 deletions

57
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,57 @@
name: CI
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:12
ports:
- 5432:5432
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v1
- name: Setup Ruby and install gems
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install dependent libraries
run: sudo apt-get install libpq-dev
- name: Bundle install
run: |
gem install bundler
bundle install --jobs 4 --retry 3
- name: Install daisyui
run: npm i daisyui
- name: Compile assets
run: bundle exec rake assets:precompile
- name: Setup Database
run: |
cp config/database.yml.github-actions config/database.yml
bundle exec rake db:create
bundle exec rake db:schema:load
env:
RAILS_ENV: test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
- name: Run RSpec
run: COVERAGE=true bundle exec rspec --require rails_helper
env:
RAILS_ENV: test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
- name: Simplecov Report
uses: aki77/simplecov-report-action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}

View file

@ -8,6 +8,7 @@ gem 'bootsnap', require: false
gem 'devise', '4.8.1'
gem 'pg', '~> 1.1'
gem 'puma', '~> 5.0'
gem 'pundit', '~> 2.2'
gem 'rails', '7.0.4'
gem 'sprockets-rails'
gem 'stimulus-rails'

View file

@ -130,6 +130,8 @@ GEM
pg (1.4.4)
puma (5.6.5)
nio4r (~> 2.0)
pundit (2.3.0)
activesupport (>= 3.0.0)
racc (1.6.0)
rack (2.2.4)
rack-test (2.0.2)
@ -253,6 +255,7 @@ DEPENDENCIES
foreman
pg (~> 1.1)
puma (~> 5.0)
pundit (~> 2.2)
rails (= 7.0.4)
rspec-rails (~> 5.1.0)
rubocop-rails

View file

@ -0,0 +1,53 @@
# frozen_string_literal: true
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
def index?
false
end
def show?
false
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
class Scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
raise NotImplementedError, "You must define #resolve in #{self.class}"
end
private
attr_reader :user, :scope
end
end

View file

@ -46,7 +46,7 @@ Rails.application.configure do
# config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ]
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
config.force_ssl = true
# Include generic and useful information about system operation, but avoid logging too much
# information to avoid inadvertent exposure of personally identifiable information (PII).
@ -68,6 +68,20 @@ Rails.application.configure do
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: ENV['SMTP_SERVER'],
port: ENV['SMTP_PORT'],
domain: 'example.com',
user_name: ENV['SMTP_USERNAME'],
password: ENV['SMTP_PASSWORD'],
authentication: 'plain',
enable_starttls_auto: true,
open_timeout: 5,
read_timeout: 5
}
config.action_mailer.default_url_options = { host: 'example.comg' }
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true

View file

@ -263,7 +263,9 @@ Devise.setup do |config|
# should add them to the navigational formats lists.
#
# The "*/*" below is required to match Internet Explorer requests.
# config.navigational_formats = ['*/*', :html]
# turbo_stream is a custom format for Turbo Streams (https://turbo.hotwired.dev/handbook/streams)
# https://stackoverflow.com/questions/36646226/undefined-method-user-url-for-devise-sessionscontrollercreate/71297012#71297012
config.navigational_formats = ['*/*', :html, :turbo_stream]
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :delete

View file

@ -1,26 +1,12 @@
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
abort('The Rails environment is running in production mode!') if Rails.env.production?
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
# Checks for pending migrations and applies them before tests are run.
# If you are not using ActiveRecord, you can remove these lines.
@ -30,34 +16,18 @@ rescue ActiveRecord::PendingMigrationError => e
puts e.to_s.strip
exit 1
end
RSpec.configure do |config|
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# You can uncomment this line to turn off ActiveRecord support entirely.
# config.use_active_record = false
# RSpec Rails can automatically mix in different behaviours to your tests
# based on their file location, for example enabling you to call `get` and
# `post` in specs under `spec/controllers`.
#
# You can disable this behaviour by removing the line below, and instead
# explicitly tag your specs with their type, e.g.:
#
# RSpec.describe UsersController, type: :controller do
# # ...
# end
#
# The different available types are documented in the features, such as in
# https://relishapp.com/rspec/rspec-rails/docs
config.infer_spec_type_from_file_location!
# Filter lines from Rails gems in backtraces.
config.filter_rails_from_backtrace!
# arbitrary gems may also be filtered via:
# config.filter_gems_from_backtrace("gem name")
config.include FactoryBot::Syntax::Methods
config.include Devise::Test::IntegrationHelpers, type: :request
config.before do
ActiveJob::Base.queue_adapter = :test
end
end
Shoulda::Matchers.configure do |config|

23
spec/support/devise.rb Normal file
View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
# https://makandracards.com/makandra/37161-rspec-devise-how-to-sign-in-users-in-request-specs
module DeviseRequestSpecHelpers
include Warden::Test::Helpers
def sign_in(resource_or_scope, resource = nil)
resource ||= resource_or_scope
scope = Devise::Mapping.find_scope!(resource_or_scope)
login_as(resource, scope: scope)
end
def sign_out(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
logout(scope)
end
end
RSpec.configure do |config|
config.include DeviseRequestSpecHelpers, type: :request
end

View file

@ -0,0 +1,31 @@
# frozen_string_literal: true
# Custom RSpec matchers for Pundit policies
RSpec::Matchers.define :permit do |action|
match do |policy|
policy.public_send("#{action}?")
end
failure_message do |policy|
"#{policy.class} does not permit #{action} on #{policy.record} for #{policy.user.inspect}."
end
failure_message_when_negated do |policy|
"#{policy.class} does not forbid #{action} on #{policy.record} for #{policy.user.inspect}."
end
end
RSpec::Matchers.define :forbid do |action|
match do |policy|
policy.public_send("#{action}?")
end
failure_message do |policy|
"#{policy.class} does not forbid #{action} on #{policy.record} for #{policy.user.inspect}."
end
failure_message_when_negated do |policy|
"#{policy.class} does not permit #{action} on #{policy.record} for #{policy.user.inspect}."
end
end