Using this project as an example, you can see how I usually write ruby code in 2022-2023.
if you just want to see the code, you can open the following files and tests for them:
- companies_fundamentals/calculations/create.rb
- companies_fundamentals/calculations/create_spec.rb
- calculator/calculate.rb
- calculator/calculate_spec.rb
- base controller (resourse based)
- base controller (non-resourse based)
- application controller - auth available here
Permitted params implemented on service layer with dry-validation here
class Contract < Dry::Validation::Contract
params do
required(:resource).schema(
Api::V1::Securities::Schema::RESOURCE_SCHEMA &
Dry::Schema.Params do
required(:company_id).filled(:integer)
end
)
end
endThe main idea is not to write repetitive code in controllers.
So you can keep your default controllers blank.
class Api::V1::CompaniesController < BaseController; endCQRS used.
Commands available here. Сalled from controllers, validate params and do action-based business logic.
Queries available here. Сalled from controllers, validate params and receive data. Queries used whitelisted ransack and some other features to provide DRY principle - available here.
Interactors available here Called from other services, needed for similar code or complex domain features that exceed the desired command size.
Blueprinter used here.
Shared specs available here.
RSpec.describe Api::V1::CompaniesController, type: :controller do
let(:serialized_resource) do
{
"id" => resource.id,
"name" => resource.name,
#...
}
end
it_behaves_like "create action" do
let(:success_params) do
{
name: "Some company",
#...
}
end
end
it_behaves_like(
"index action",
filter_params: %i[country_id_eq default_currency_id_eq] # some params for shared examples
)
it_behaves_like "show action"
it_behaves_like "update action" do
let(:success_params) do
{
name: "Other company",
# ...
}
end
end
it_behaves_like "destroy action success"
end