Update `Ajax::RelationshipController` to use usernames; Test Use Case
This commit is contained in:
parent
4a1ed5394a
commit
d609435f7c
|
@ -8,8 +8,10 @@ class Ajax::RelationshipController < AjaxController
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
params.require :target_user
|
||||||
|
|
||||||
UseCase::Relationship::Create.call(
|
UseCase::Relationship::Create.call(
|
||||||
current_user_id: current_user.id,
|
current_user: current_user.screen_name,
|
||||||
target_user: params[:target_user],
|
target_user: params[:target_user],
|
||||||
type: params[:type]
|
type: params[:type]
|
||||||
)
|
)
|
||||||
|
@ -23,7 +25,7 @@ class Ajax::RelationshipController < AjaxController
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
UseCase::Relationship::Destroy.call(
|
UseCase::Relationship::Destroy.call(
|
||||||
current_user_id: current_user.id,
|
current_user: current_user.screen_name,
|
||||||
target_user: params[:target_user],
|
target_user: params[:target_user],
|
||||||
type: params[:type]
|
type: params[:type]
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,6 +18,30 @@ class AjaxController < ApplicationController
|
||||||
return_response
|
return_response
|
||||||
end
|
end
|
||||||
|
|
||||||
|
rescue_from(KeyError) do |e|
|
||||||
|
Sentry.capture_exception(e)
|
||||||
|
|
||||||
|
@response = {
|
||||||
|
success: false,
|
||||||
|
message: "Missing parameter: #{e.key}",
|
||||||
|
status: :err
|
||||||
|
}
|
||||||
|
|
||||||
|
return_response
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue_from(Dry::Types::CoercionError, Dry::Types::ConstraintError) do |e|
|
||||||
|
Sentry.capture_exception(e)
|
||||||
|
|
||||||
|
@response = {
|
||||||
|
success: false,
|
||||||
|
message: "Invalid parameter",
|
||||||
|
status: :err
|
||||||
|
}
|
||||||
|
|
||||||
|
return_response
|
||||||
|
end
|
||||||
|
|
||||||
rescue_from(ActiveRecord::RecordNotFound) do |e|
|
rescue_from(ActiveRecord::RecordNotFound) do |e|
|
||||||
Sentry.capture_exception(e)
|
Sentry.capture_exception(e)
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,6 @@ module Errors
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ParamIsMissing < BadRequest
|
|
||||||
end
|
|
||||||
|
|
||||||
class InvalidBanDuration < BadRequest
|
class InvalidBanDuration < BadRequest
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,4 +4,6 @@ require 'dry-types'
|
||||||
|
|
||||||
module Types
|
module Types
|
||||||
include Dry.Types()
|
include Dry.Types()
|
||||||
|
|
||||||
|
RelationshipTypes = Types::String.enum('follow')
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,13 +15,5 @@ module UseCase
|
||||||
def call
|
def call
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def not_blank!(*args)
|
|
||||||
args.each do |arg|
|
|
||||||
raise Errors::ParamIsMissing if instance_variable_get("@#{arg}").blank?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -6,15 +6,11 @@ require "errors"
|
||||||
module UseCase
|
module UseCase
|
||||||
module Relationship
|
module Relationship
|
||||||
class Create < UseCase::Base
|
class Create < UseCase::Base
|
||||||
option :current_user_id, type: Types::Coercible::Integer
|
option :current_user, type: Types::Coercible::String
|
||||||
option :target_user, type: Types::Coercible::String
|
option :target_user, type: Types::Coercible::String
|
||||||
option :type, type: Types::Coercible::String
|
option :type, type: Types::RelationshipTypes
|
||||||
|
|
||||||
def call
|
def call
|
||||||
not_blank! :current_user_id, :target_user, :type
|
|
||||||
|
|
||||||
type = @type.downcase
|
|
||||||
ensure_type(type)
|
|
||||||
source_user = find_source_user
|
source_user = find_source_user
|
||||||
target_user = find_target_user
|
target_user = find_target_user
|
||||||
|
|
||||||
|
@ -31,19 +27,14 @@ module UseCase
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def ensure_type(type)
|
|
||||||
raise Errors::BadRequest unless type == 'follow'
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_source_user
|
def find_source_user
|
||||||
user_id = @current_user_id
|
return current_user if current_user.is_a?(::User)
|
||||||
::User.find(user_id)
|
::User.find_by!(screen_name: current_user)
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
raise Errors::UserNotFound
|
raise Errors::UserNotFound
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_target_user
|
def find_target_user
|
||||||
target_user = @target_user
|
|
||||||
return target_user if target_user.is_a?(::User)
|
return target_user if target_user.is_a?(::User)
|
||||||
::User.find_by!(screen_name: target_user)
|
::User.find_by!(screen_name: target_user)
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
|
|
@ -6,15 +6,11 @@ require "errors"
|
||||||
module UseCase
|
module UseCase
|
||||||
module Relationship
|
module Relationship
|
||||||
class Destroy < UseCase::Base
|
class Destroy < UseCase::Base
|
||||||
option :current_user_id, type: Types::Coercible::Integer
|
option :current_user, type: Types::Coercible::String | Types.Instance(User)
|
||||||
option :target_user, type: Types::Coercible::String
|
option :target_user, type: Types::Coercible::String | Types.Instance(User)
|
||||||
option :type, type: Types::Coercible::String
|
option :type, type: Types::RelationshipTypes
|
||||||
|
|
||||||
def call
|
def call
|
||||||
not_blank! :current_user_id, :target_user, :type
|
|
||||||
|
|
||||||
type = @type.downcase
|
|
||||||
ensure_type(type)
|
|
||||||
source_user = find_source_user
|
source_user = find_source_user
|
||||||
target_user = find_target_user
|
target_user = find_target_user
|
||||||
|
|
||||||
|
@ -31,20 +27,13 @@ module UseCase
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def ensure_type(type)
|
|
||||||
raise Errors::BadRequest unless type == 'follow'
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_source_user
|
def find_source_user
|
||||||
user_id = @current_user_id
|
::User.find_by!(screen_name: current_user)
|
||||||
::User.find(user_id)
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
raise Errors::UserNotFound
|
raise Errors::UserNotFound
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_target_user
|
def find_target_user
|
||||||
target_user = @target_user
|
|
||||||
return target_user if target_user.is_a?(::User)
|
|
||||||
::User.find_by!(screen_name: target_user)
|
::User.find_by!(screen_name: target_user)
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
raise Errors::UserNotFound
|
raise Errors::UserNotFound
|
||||||
|
|
|
@ -5,9 +5,9 @@ require "rails_helper"
|
||||||
|
|
||||||
describe Ajax::RelationshipController, type: :controller do
|
describe Ajax::RelationshipController, type: :controller do
|
||||||
shared_examples_for "params is empty" do
|
shared_examples_for "params is empty" do
|
||||||
let(:params) { { type: type } } # type is still required as it's part of the route
|
let(:params) { }
|
||||||
|
|
||||||
include_examples "ajax does not succeed", "param is missing"
|
include_examples "ajax does not succeed", "is required"
|
||||||
end
|
end
|
||||||
|
|
||||||
let!(:user) { FactoryBot.create(:user) }
|
let!(:user) { FactoryBot.create(:user) }
|
||||||
|
@ -60,7 +60,7 @@ describe Ajax::RelationshipController, type: :controller do
|
||||||
let(:type) { "dick" }
|
let(:type) { "dick" }
|
||||||
|
|
||||||
it_behaves_like "params is empty"
|
it_behaves_like "params is empty"
|
||||||
include_examples "ajax does not succeed", "Bad Request"
|
include_examples "ajax does not succeed", "Invalid parameter"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -85,8 +85,6 @@ describe Ajax::RelationshipController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like "params is empty"
|
|
||||||
|
|
||||||
context "target_user does not exist" do
|
context "target_user does not exist" do
|
||||||
let(:target_user) { "peter-witzig" }
|
let(:target_user) { "peter-witzig" }
|
||||||
|
|
||||||
|
@ -114,8 +112,7 @@ describe Ajax::RelationshipController, type: :controller do
|
||||||
context "type = 'dick'" do
|
context "type = 'dick'" do
|
||||||
let(:type) { "dick" }
|
let(:type) { "dick" }
|
||||||
|
|
||||||
it_behaves_like "params is empty"
|
include_examples "ajax does not succeed", "Invalid parameter"
|
||||||
include_examples "ajax does not succeed", "Bad Request"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
require "use_case/relationship/create"
|
||||||
|
require "errors"
|
||||||
|
|
||||||
|
describe UseCase::Relationship::Create do
|
||||||
|
shared_examples_for "valid relationship type" do
|
||||||
|
context "current_user does not exist" do
|
||||||
|
let(:current_user) { "Schweinsbraten" }
|
||||||
|
|
||||||
|
include_examples "raises an error", Errors::UserNotFound
|
||||||
|
end
|
||||||
|
|
||||||
|
context "target_user does not exist" do
|
||||||
|
let(:target_user) { "peterwitzig" }
|
||||||
|
|
||||||
|
include_examples "raises an error", Errors::UserNotFound
|
||||||
|
end
|
||||||
|
|
||||||
|
context "target_user is current_user" do
|
||||||
|
let(:target_user) { user1.screen_name }
|
||||||
|
|
||||||
|
include_examples "raises an error", Errors::SelfAction
|
||||||
|
end
|
||||||
|
|
||||||
|
context "target_user is different from current_user" do
|
||||||
|
its([:status]) { is_expected.to eq(201) }
|
||||||
|
its([:extra]) { is_expected.to eq(target_user: user2) }
|
||||||
|
|
||||||
|
it "creates a relationship" do
|
||||||
|
expect { subject }.to change { Relationship.count }.by(1)
|
||||||
|
last_relationship = Relationship.last
|
||||||
|
expect(last_relationship.source_id).to eq(user1.id)
|
||||||
|
expect(last_relationship.target_id).to eq(user2.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:base_params) do
|
||||||
|
{
|
||||||
|
current_user: current_user,
|
||||||
|
target_user: target_user,
|
||||||
|
type: type
|
||||||
|
}
|
||||||
|
end
|
||||||
|
let(:params) { base_params }
|
||||||
|
let(:current_user) { user1.screen_name }
|
||||||
|
let(:target_user) { user2.screen_name }
|
||||||
|
let(:type) { nil }
|
||||||
|
|
||||||
|
# test data:
|
||||||
|
let!(:user1) { FactoryBot.create(:user, screen_name: "timallen") }
|
||||||
|
let!(:user2) { FactoryBot.create(:user, screen_name: "joehilyar") }
|
||||||
|
|
||||||
|
subject { described_class.call(params) }
|
||||||
|
|
||||||
|
context "type = 'follow'" do
|
||||||
|
let(:type) { "follow" }
|
||||||
|
|
||||||
|
include_examples "valid relationship type"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "type = 'dick'" do
|
||||||
|
let(:type) { "dick" }
|
||||||
|
|
||||||
|
include_examples "raises an error", Dry::Types::ConstraintError
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,73 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
require "use_case/relationship/destroy"
|
||||||
|
require "errors"
|
||||||
|
|
||||||
|
describe UseCase::Relationship::Destroy do
|
||||||
|
shared_examples_for "valid relationship type" do
|
||||||
|
its([:status]) { is_expected.to eq(204) }
|
||||||
|
its([:extra]) { is_expected.to eq(target_user: user2) }
|
||||||
|
|
||||||
|
context "relationship exists" do
|
||||||
|
before do
|
||||||
|
user1.public_send(type, user2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "destroys a relationship" do
|
||||||
|
expect { subject }.to change { Relationship.count }.by(-1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "relationship does not exist" do
|
||||||
|
it "does not change anything at all" do
|
||||||
|
expect { subject }.to change { Relationship.count }.by(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "current_user does not exist" do
|
||||||
|
let(:current_user) { "Schweinsbraten" }
|
||||||
|
let(:target_user) { user2.screen_name }
|
||||||
|
|
||||||
|
include_examples "raises an error", Errors::UserNotFound
|
||||||
|
end
|
||||||
|
|
||||||
|
context "target_user does not exist" do
|
||||||
|
let(:current_user) { user1.screen_name }
|
||||||
|
let(:target_user) { "peterwitzig" }
|
||||||
|
|
||||||
|
include_examples "raises an error", Errors::UserNotFound
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:base_params) do
|
||||||
|
{
|
||||||
|
current_user: current_user,
|
||||||
|
target_user: target_user,
|
||||||
|
type: type
|
||||||
|
}
|
||||||
|
end
|
||||||
|
let(:params) { base_params }
|
||||||
|
let(:current_user) { user1.screen_name }
|
||||||
|
let(:target_user) { user2.screen_name }
|
||||||
|
let(:type) { nil }
|
||||||
|
|
||||||
|
# test data:
|
||||||
|
let!(:user1) { FactoryBot.create(:user, screen_name: "timallen") }
|
||||||
|
let!(:user2) { FactoryBot.create(:user, screen_name: "joehilyar") }
|
||||||
|
|
||||||
|
subject { described_class.call(params) }
|
||||||
|
|
||||||
|
context "type = 'follow'" do
|
||||||
|
let(:type) { "follow" }
|
||||||
|
|
||||||
|
include_examples "valid relationship type"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "type = 'dick'" do
|
||||||
|
let(:type) { "dick" }
|
||||||
|
|
||||||
|
include_examples "raises an error", Dry::Types::ConstraintError
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,11 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.shared_examples_for "raises an error" do |error_klass|
|
||||||
|
it "raises an error" do
|
||||||
|
expect { subject }.to raise_error(kind_of(error_klass))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
RSpec.shared_examples_for "ajax does not succeed" do |part_of_error_message|
|
RSpec.shared_examples_for "ajax does not succeed" do |part_of_error_message|
|
||||||
it "ajax does not succeed" do
|
it "ajax does not succeed" do
|
||||||
subject
|
subject
|
||||||
|
|
Loading…
Reference in New Issue