50 lines
1.5 KiB
Ruby
50 lines
1.5 KiB
Ruby
module Listings
|
|
# This service wraps listing purchses in a transaction which verifies that
|
|
# the purchaser has enough credits to complete this process.
|
|
class Create
|
|
# @param listing [Listing] an initialized but not yet persisted listing
|
|
# @param purchaser [User] the user attempting to purchase the listing
|
|
# @param cost [Integer] the number of credits the user has to spend
|
|
# @return [Listings::Create] the service itself, used for the success? check
|
|
def self.call(listing, purchaser:, cost:)
|
|
new(listing, purchaser, cost).call
|
|
end
|
|
|
|
def initialize(listing, purchaser, cost)
|
|
@listing = listing
|
|
@purchaser = purchaser
|
|
@cost = cost
|
|
@success = false
|
|
end
|
|
|
|
def call
|
|
ActiveRecord::Base.transaction do
|
|
# Subtract credits
|
|
enough_credits = Credits::Buyer.call(
|
|
purchaser: @purchaser,
|
|
purchase: @listing,
|
|
cost: @cost,
|
|
)
|
|
|
|
raise ActiveRecord::Rollback unless enough_credits
|
|
|
|
# Update the listing
|
|
@listing.bumped_at = Time.current
|
|
@listing.published = true
|
|
@listing.originally_published_at = Time.current
|
|
|
|
# Since we can't raise ActiveRecord errors in this transaction
|
|
# due to the fact that we need to display them in the :new view,
|
|
# we manually rollback the transaction if there are validation errors
|
|
raise ActiveRecord::Rollback unless @listing.save
|
|
|
|
@success = true
|
|
end
|
|
self
|
|
end
|
|
|
|
def success?
|
|
@success
|
|
end
|
|
end
|
|
end
|