Collection of classes, configs, scripts, generators for Ruby on Rails helping you get things done, better.
Add one of these lines to your application's Gemfile
:
# version released to RubyGems (recommended)
gem 'auxiliary_rails'
# or latest version from the repository
gem 'auxiliary_rails', git: 'https://github.com/ergoserv/auxiliary_rails'
# or from a specific branch of the GitHub repository
gem 'auxiliary_rails', github: 'ergoserv/auxiliary_rails', branch: 'develop'
# or from a local path (for development and testing purposes)
gem 'auxiliary_rails', path: '../auxiliary_rails'
And then execute:
$ bundle
Or install it yourself as:
$ gem install auxiliary_rails
Install gem into the system (e.g. using gem install auxiliary_rails
) then:
auxiliary_rails new APP_PATH
# or add `--develop` option to pull the most recent template from repository
auxiliary_rails new APP_PATH --develop
Or use rails new
command specifying --template
argument:
rails new APP_PATH --database=postgresql --template=https://raw.githubusercontent.com/ergoserv/auxiliary_rails/develop/templates/rails/elementary.rb --skip-action-cable --skip-coffee --skip-test
# Install everything at once
rails generate auxiliary_rails:install
# Install one by one
rails generate auxiliary_rails:install_commands
rails generate auxiliary_rails:install_errors
rails generate auxiliary_rails:install_errors_controller
# API resource generator
rails generate auxiliary_rails:api_resource
# Command generator
rails generate auxiliary_rails:command
# Service generator
rails generate auxiliary_rails:service
Read article Building an API for more details.
Use generator to generate appropriate classes and files (Resource, Entity, Helper, Spec) for the specified end-point:
rails generate auxiliary_rails:api_resource
Variation of implementation of Command pattern.
Read post Command Objects - a.k.a Service Objects in Ruby on Rails - The Ergonomic Way for more details.
# app/commands/application_command.rb
class ApplicationCommand < AuxiliaryRails::Application::Command
end
# app/commands/register_user_command.rb
class RegisterUserCommand < ApplicationCommand
# Define command arguments
# using `param` or `option` methods provided by dry-initializer
# https://dry-rb.org/gems/dry-initializer/3.0/
param :email
param :password
# Define the results of the command using `attr_reader`
# and set it as a regular instance var inside the command
attr_reader :user
# Regular Active Model Validations can be used to validate params
# https://api.rubyonrails.org/classes/ActiveModel/Validations.html
# Use #valid?, #invalid?, #validate! methods to engage validations
validates :password, length: { in: 8..32 }
# Define the only public method `#perform` where command's flow is defined
def perform
# Use `return failure!` and `return success!` inside `#perform` method
# to control exits from the command with appropriate status.
# Use `return failure!` to exit from the command with failure
return failure! if registration_disabled?
# Method `#transaction` is a shortcut for `ActiveRecord::Base.transaction`
transaction do
# Keep the `#perform` method short and clean, put all the steps, actions
# and business logic into meaningful and self-explanatory methods
@user = create_user
# Use `error!` method to interrupt the flow raising an error
error! unless user.persistent?
send_notifications
# ...
end
# Always end the `#perform` method with `success!`.
# It will set the proper command's execution status.
success!
end
private
def create_user
User.create(email: email, password: password)
end
def send_notifications
# ...
end
end
### usage ###
class RegistrationsController
def register
cmd = RegisterUserCommand.call(params[:email], params[:password])
if cmd.success?
redirect_to user_path(cmd.user) and return
else
@errors = cmd.errors
end
### OR ###
RegisterUserCommand.call(params[:email], params[:password])
.on(:success) do
redirect_to dashboard_path and return
end
.on(:failure) do |cmd|
@errors = cmd.errors
end
end
end
Custom error objects. Read article Error Handling for more details.
# app/errors/application_error.rb
class ApplicationError < AuxiliaryRails::Application::Error
end
# app/forms/application_form.rb
class ApplicationForm < AuxiliaryRails::Application::Form
end
# app/forms/company_registration_form.rb
class CompanyRegistrationForm < ApplicationForm
# Define form attributes
attribute :company_name, :string
attribute :email, :string
# Define form submission results
attr_reader :company
# Regular Active Model Validations can be used to validate attributes
# https://api.rubyonrails.org/classes/ActiveModel/Validations.html
validates :company_name, presence: true
validates :email, email: true
def perform
# Perform business logic here
# Use `attr_reader` to expose the submission results.
@company = create_company
# Return `failure!` to indicate failure and stop execution
return failure! if @company.invalid?
send_notification if email.present?
# Always end with `success!` method call to indicate success
success!
end
private
def create_comany
Company.create(name: company_name)
end
def send_notification
# mail to: email
end
end
### Usage ###
form = CompanyRegistrationForm.call(params[:company])
if form.success?
redirect_to company_path(form.company) and return
else
@errors = form.errors
end
# app/queries/application_query.rb
class ApplicationQuery < AuxiliaryRails::Application::Query
end
# app/queries/authors_query.rb
class AuthorsQuery < ApplicationQuery
default_relation Author.all
option :name_like, optional: true
option :with_books, optional: true
def perform
if recent == true
# equivalent to `@query = @query.order(:created_at)`:
query order(:created_at)
end
if name_like.present?
query with_name_like(name_like)
end
end
private
def with_name_like(value)
where('authors.name LIKE ?', "%#{value}%")
end
end
# app/queries/authors_with_books_query.rb
class AuthorsWithBooksQuery < AuthorsQuery
option :min_book_count, default: { 3 }
def perform
query joins(:books)
.group(:author_id)
.having('COUNT(books.id) > ?', min_book_count)
end
end
### Usage ###
# it is possible to wrap query object in a scope and use as a regular scope
# app/models/author.rb
class Author < ApplicationRecord
scope :name_like, ->(value) { AuthorsQuery.call(name_like: value) }
end
authors = Author.name_like('Arthur')
# or call query directly
authors = AuthorsWithBooksQuery.call(min_book_count: 10)
Read Service Modules for more details.
Service Generator
rails generate auxiliary_rails:service
Service Config - provides a unified access to a service configs and loads the first found from:
- Constant (
MyService::CONFIG
) - Application config file (
config/settings.yml
, see gemconfig
) - Service config file (
config/services/my_service.yml
)
# app/services/my_service.rb
module MyService
extend AuxiliaryRails::Application::Service
end
# usage
MyService.config.some_key
current_controller?(*ctrl_names)
current_action?(*action_names)
display_name(resource)
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/ergoserv/auxiliary_rails.
The gem is available as open source under the terms of the MIT License.
This gem was created and is maintained by ErgoServ.
If you like what you see and would like to hire us or join us, get in touch!