Readymade

Gem Version

This gems contains basic components to follow ABDI architecture

Tested with ruby:

  • 3.1
  • 3.0
  • 2.7

Installation

Add this line to your application’s Gemfile:

“by gem ‘readymade’

And then execute:

$ bundle install

Or install it yourself as:

$ gem install readymade

Usage

Inherit your components from: * Readymade::Response * Readymade::Form * Readymade::InstantForm * Readymade::Action * Readymade::Operation

Readymade::Response

“by response = Readymade::Response.new(:success, my_data: data) response.success? # true response = Readymade::Response.new(:fail, errors: errors) response.success? # false response.fail? # true response.status # ‘fail’ response.data # { errors: { some: ‘errors’ } }

Readymade::Form

Check more form features examples in lib/readymade/form.rb

“by class Orders::Forms::Create < Readymade::Form PERMITTED_ATTRIBUTES = %i[email name category country customer] REQUIRED_ATTRIBUTES = %i[email]

validates :customer, presence: true, if: args[:validate_customer] end

order_form = Orders::Forms::Create.new(params, order: order, validate_customer: false)

order_form.valid? # true

form_options

“by

app/forms/my_form.rb

class MyForm < Readymade::Form PERMITTED_ATTRIBUTES = %i[email name category country] REQUIRED_ATTRIBUTES = %i[email]

def form_options { categories: args[:company].categories, countries: Country.all } end end

“by

app/controllers/items_controller.rb

def new @form = MyForm.form_options(company: current_company) end

“im / app/views/items/new.html.slim

= f.select :category, collection: @form[:categories]

= f.text_field :email, required: @form.required?(:email) # true

Readymade::InstantForm

Permit params and validates presence inline

“by Readymade::InstantForm.new(my_params, permitted: %i[name phone], required: %i[email]) # permits: name, phone, email; validates on presence: email

Readymade::Action

“by class Orders::Actions::SendNotifications < Readymade::Action def call send_email send_push send_slack

response(:success, record: record, any_other_data: data)

end end

“by response = Orders::Actions::SendNotifications.call(order: order)

response.fail? # false response.success? # true response.data[:record] response.data[:any_other_data]

.call_async - any action could we call async (using ActiveJob)

“by class Orders::Actions::SendNotifications < Readymade::Action def call send_email send_push send_slack

response(:success, record: record, any_other_data: data)

end … end

Orders::Actions::SendNotifications.call_async(order: order) Orders::Actions::SendNotifications.call_async!(order: order, queue_as: :my_queue) # job will be executed in ‘my_queue’

Important! Make sure your sidekiq configuration has ‘my_queue’ queue

.call! - raise error unless response is success

(action must return Readymade::Response.new(:success))

“by class Orders::Actions::SendNotifications < Readymade::Action def call! send_email return response(:fail, errors: errors) unless email_sent? send_push send_slack

response(:success, record: record, any_other_data: data)

end … end

Orders::Actions::SendNotifications.call!(order: order) # raise error if response is fail

.call + conisder_success: true

“by class Orders::Actions::SendNotifications < Readymade::Action def call! send_email return response(:skip, consider_success: true) if skip_email? send_push send_slack

response(:success, record: record, any_other_data: data)

end … end

Orders::Actions::SendNotifications.call!(order: order) # does not raise error if skip_email? returns true

.call_async! - runs in background and raise error unless response is success

(action must return Readymade::Response.new(:success))

“by class Orders::Actions::SendNotifications < Readymade::Action def call! send_email return response(:fail, errors: errors) unless email_sent? send_push send_slack

response(:success, record: record, any_other_data: data)

end … end

Orders::Actions::SendNotifications.call_async!(order: order) # job will be failed

Readymade::Operation

Provides set of help methods like: build_form, form_valid?, validation_fail, save_record, etc.

“by class Orders::Operations::Create < Readymade::Operation def call build_record build_form return validation_fail unless form_valid?

assign_attributes
return validation_fail unless record_valid?

save_record

success(record: record)

end end

Readymade::Controller::Serialization

“by class MyController < ApplicationController include Readymade::Controller::Serialization end

Serialization helpers for controllers. Dependencies that must be installed on your own: - blueprinter - pagy - api-pagination

Readymade::Model::ApiAttachable

Add base64 attachments format for your models

“by class User < ApplicationRecord has_one_attached :avatar has_many_attached :images include Readymade::Model::ApiAttachable # must be included after has_one_attached, has_many_attached declaration # api_file = { # base64: ‘iVBORw0KGgoAAA….’, # filename: ‘my_avatar.png’ # } # record.avatar = api_file 🎉 end

copy spec/support/api_attachable.rb

“by def to_api_file(file) { base64: Base64.encode64(file.read), filename: file.original_filename } end

“by

rspec example

let(:avatar) { Rack::Test::UploadedFile.new(Rails.root.join(‘spec/support/assets/test-image.png’), ‘image/png’) } let(:params) { { user: attributes_for(:user).merge!(avatar: to_api_file(avatar)) } }

Readymade::Model::Filterable

“by class User < ApplicationRecord include Readyamde::Model::Filterable

scope :by_status, ->(status) { where(status: status) } scope :by_role, ->(role) { where(role: role) } end

“by User.all.filter_collection({ by_status: ‘active’, by_role: ‘manager’ }) User.all.filter_collection({ by_status: ‘active’, by_role: ‘manager’ }, chain_with: :or) # active OR manager

Readymade::Model::ValidatableEnum

Instead of raised error when enum value is not valid, it adds error to the record

“by class User < ApplicationRecord include Readymade::Model::ValidatableEnum

enum status: { inactive: 0, active: 10 } enum role: { customer: 0, admin: 10 } validatable_enum :status, :role end

“by user = User.new(status: ‘archived’, role: ‘superadmin’) user.validate # false user.errors.full_messages # [Role superadmin is not a valid role, Status archived is not a valid status]

Development

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.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/OrestF/readymade. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Lead project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.