docbrown/app/services/user_subscriptions/create_from_controller_params.rb
Alex 9ee024f9d0
UserSubscription backend refactor (#9060)
* Refactor controller validations to model

* Update specs and move current email validation back

* Refactor #subscribed

* Cleanup UserSubscriptions::Create service

* Refactor service

* Move source inside of call for clarity

* Specs for UserSubscription::Create

* Cleanup spec

* Fix Article spec

* Updated for subscriber_email

* Add comment for explicitness of subscriber_email

* Fix reference in comment...oops!

* I know what I'm doing...sometimes...maybe

* Rename CachChecker - Subscription to IsSubscribed

* Use include vs eq in specs for error messages

* attr_accessor --> attr_reader

* Don't explicitly set nil

* Rename Create service to CreateFromService

* Use errors_as_sentence

* Rename service to CreateFromControllerParams

* Assign Struct to a new constant
2020-07-02 12:08:37 -04:00

71 lines
2.2 KiB
Ruby

module UserSubscriptions
# When creating a UserSubscription from a controller/user interation on the
# frontend, we need to do some extra validations and logic.
class CreateFromControllerParams
attr_reader :user, :source_type, :source_id, :subscriber_email, :response
Response = Struct.new(:success, :data, :error, keyword_init: true)
def self.call(*args)
new(*args).call
end
def initialize(user, user_subscription_params)
@user = user
@source_type = user_subscription_params[:source_type]
@source_id = user_subscription_params[:source_id]
@response = Response.new(success: false)
# TODO: [@thepracticaldev/delightful]: uncomment this once email confirmation is re-enabled
# @subscriber_email = user_subscription_params[:subscriber_email]
end
def call
return response if invalid_source_type?
source = source_type.constantize.find_by(id: source_id)
return response if invalid_source?(source)
# TODO: [@thepracticaldev/delightful]: uncomment this once email confirmation is re-enabled
# return response if subscriber_email_mismatch?
user_subscription = source.build_user_subscription(user)
if user_subscription.save
response.success = true
response.data = user_subscription
else
response.error = user_subscription.errors_as_sentence
end
response
end
private
def invalid_source_type?
return false if UserSubscription::ALLOWED_TYPES.include?(source_type)
response.error = "Invalid source_type."
true
end
def invalid_source?(source)
return false if source
response.error = "Source not found."
true
end
def subscriber_email_mismatch?
# This checks if the email address the user saw/consented to share is the
# same as their current email address. A mismatch occurs if a user updates
# their email address in a new/separate tab and then tries to subscribe on
# the old/stale tab without refreshing. In that case, the user would have
# consented to share their old email address instead of the current one.
return false if user.email == subscriber_email
response.error = "Subscriber email mismatch."
true
end
end
end