Skip to content

Instantly share code, notes, and snippets.

@yurko
Last active February 18, 2019 13:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yurko/1199b59849c56dbcd54de2c1ad20ba05 to your computer and use it in GitHub Desktop.
Save yurko/1199b59849c56dbcd54de2c1ad20ba05 to your computer and use it in GitHub Desktop.
railway oriented
module Carousel
class Reorder
extend Dry::Initializer
include Dry::Monads::Either::Mixin
param :scope, reader: :private
param :params, reader: :private
def call
context = OpenStruct.new(
scope: scope,
params: params
)
response = transaction.call(context)
.fmap { |result| Service::Response.new(data: result) }
.value
if block_given?
yield response
else
response
end
end
private
def transaction
Dry.Transaction(container: container) do
step :validate_params
step :reset_priorities
step :update_priorities
end
end
def container
Hash.new { |hash, key| hash[key] = method(key) }.with_indifferent_access
end
def validate_params(context)
params = context.params
schema = Dry::Validation.Schema do
each do
schema do
required(:id).filled
end
end
end
validation = schema.(params)
if validation.success?
Right(context)
else
Left(Service::Response.new(errors: [I18n.t("invalid_params")]))
end
end
def reset_priorities(context)
scope = context.scope
scope.update_all(priority: 0)
Right(context)
end
def update_priorities(context)
params = context.params
params.reverse.map.with_index do |e, priority|
scope.find(e[:id]).update_columns(priority: priority)
end
Right(context)
end
end
end
require "rails_helper"
describe Carousel::Reorder, type: [:service] do
let(:tenant) { create(:tenant) }
let!(:thing_1) { create :thing, :public_approved, :top_rated, priority: Faker::Number.number(1), tenant: tenant }
let!(:thing_2) { create :thing, :public_approved, :top_rated, priority: Faker::Number.number(1), tenant: tenant }
let!(:thing_3) { create :thing, :public_approved, :top_rated, priority: Faker::Number.number(1), tenant: tenant }
let(:scope) { Thing.public_approved(tenant) }
let(:params) do
Array[Hash[id: thing_2.id], Hash[id: thing_1.id], Hash[id: thing_3.id]]
end
describe "#call" do
context "success" do
subject { described_class.new(scope, params) }
it "changes things priorities" do
subject.call
# priority acc. to reversed order
expect(thing_3.reload.priority).to eq 0
expect(thing_1.reload.priority).to eq 1
expect(thing_2.reload.priority).to eq 2
end
end
context "failure" do
subject { described_class.new(scope, params) }
let(:params) do
Array[Hash[id: nil]]
end
it "has errors" do
result = subject.call
expect(result).to be_failure
expect(result.errors).to eq [I18n.t("invalid_params", locale: tenant.locale)]
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment