Skip to content
This repository has been archived by the owner on Jul 30, 2019. It is now read-only.

Commit

Permalink
Merge eaf91ce into ebe2461
Browse files Browse the repository at this point in the history
  • Loading branch information
jessieay committed Jun 3, 2016
2 parents ebe2461 + eaf91ce commit 903fe73
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 320 deletions.
59 changes: 27 additions & 32 deletions app/controllers/bids_controller.rb
Expand Up @@ -23,31 +23,40 @@ def new
end

def confirm
bid = PlaceBid.new(params: params, user: current_user, via: via).dry_run
@confirm_bid = ConfirmBidViewModel.new(auction: Auction.find(params[:auction_id]), bid: bid)
rescue UnauthorizedError => error
flash[:error] = error.message
redirect_to new_auction_bid_path(params[:auction_id])
end
bid = PlaceBid.new(params: params, bidder: current_user, via: via)
auction = Auction.find(params[:auction_id])

def create
unless current_user.sam_accepted?
fail UnauthorizedError, "You must have a valid SAM.gov account to place a bid"
if bid.valid?
readonly_bid = bid.dry_run
@confirm_bid = ConfirmBidViewModel.new(auction: auction, bid: readonly_bid)
else
flash[:error] = bid.errors.full_messages.to_sentence
redirect_to new_auction_bid_path(auction)
end
end

@bid = PlaceBid.new(params: params, user: current_user, via: via).perform
def create
@bid = PlaceBid.new(params: params, bidder: current_user, via: via)

respond_to do |format|
format.html do
flash[:bid] = "success"
redirect_to auction_path(@bid.auction)
if @bid.perform
respond_to do |format|
format.html do
flash[:bid] = "success"
redirect_to auction_path(@bid.auction)
end
format.json { render json: @bid.bid, serializer: BidSerializer }
end
format.json do
render json: @bid, serializer: BidSerializer
else
respond_to do |format|
format.html do
flash[:error] = @bid.errors.full_messages.to_sentence
redirect_to new_auction_bid_path(params[:auction_id])
end
format.json do
render json: { error: @bid.errors.full_messages.to_sentence }, status: 403
end
end
end
rescue UnauthorizedError => e
respond_error(e, redirect_path: new_auction_bid_path(params[:auction_id]))
end

rescue_from 'ActiveRecord::RecordNotFound' do
Expand All @@ -57,18 +66,4 @@ def create
end
end
end

private

def respond_error(error, redirect_path: '/')
respond_to do |format|
format.html do
flash[:error] = error.message
redirect_to redirect_path
end
format.json do
render json: { error: error.message }, status: 403
end
end
end
end
85 changes: 14 additions & 71 deletions app/services/place_bid.rb
@@ -1,94 +1,37 @@
class PlaceBid
BID_LIMIT = 3500
include ActiveModel::Validations

BID_INCREMENT = 1

attr_reader :bid, :params, :user, :via
attr_reader :params, :bidder, :via

validates_with PlaceBidValidator

def initialize(params:, user:, via:nil)
def initialize(params:, bidder:, via: nil)
@params = params
@user = user
@bidder = bidder
@via = via
end

def perform
validate_bid_data
create_bid
if valid?
bid.save
end
end

def dry_run
validate_bid_data
unsaveable_bid
bid.readonly!
bid
end

def create_bid
@bid ||= Bid.create(
amount: amount,
bidder_id: user.id,
auction_id: auction.id,
via: via
)
def bid
@_bid ||= Bid.new(amount: amount, auction: auction, bidder: bidder, via: via)
end

def unsaveable_bid
@bid ||= Bid.new(
amount: amount,
bidder_id: user.id,
auction_id: auction.id,
via: via
)

@bid.readonly!
@bid
end

private

def auction
@auction ||= Auction.find(params[:auction_id])
end

def max_allowed_bid
rules.max_allowed_bid
end

def validate_bid_data
unless auction_available?
fail UnauthorizedError, 'Auction not available'
end

unless user_can_bid?
fail UnauthorizedError, 'You are not allowed to bid on this auction'
end

if amount.to_i != amount
fail UnauthorizedError, 'Bids must be in increments of one dollar'
end

if amount > BID_LIMIT
fail UnauthorizedError, 'Bid too high'
end

if amount <= 0
fail UnauthorizedError, 'Bid amount out of range'
end

if amount > max_allowed_bid
fail UnauthorizedError, "Bids cannot be greater than the current max bid"
end
end

def auction_available?
AuctionStatus.new(auction).available?
end

def user_can_bid?
rules.user_can_bid?(user)
end

def rules
@_rules ||= RulesFactory.new(auction).create
end

def amount
params_amount = params[:bid][:amount]
params_amount = params_amount.delete(',') if params_amount.is_a?(String)
Expand Down
33 changes: 33 additions & 0 deletions app/validators/place_bid_validator.rb
@@ -0,0 +1,33 @@
class PlaceBidValidator < ActiveModel::Validator
def validate(bid)
unless user_can_bid?(bid)
add_error(bid, 'permissions')
end

if bid.amount <= 0
add_error(bid, 'amount.below_zero')
end

if bid.amount > max_allowed_bid(bid)
add_error(bid, 'amount.greater_than_max')
end
end

private

def add_error(bid, message)
bid.errors.add :base, I18n.t("activerecord.errors.models.bid.#{message}")
end

def user_can_bid?(bid)
rules(bid).user_can_bid?(bid.bidder)
end

def max_allowed_bid(bid)
rules(bid).max_allowed_bid
end

def rules(bid)
RulesFactory.new(bid.auction).create
end
end
5 changes: 5 additions & 0 deletions config/locales/en.yml
Expand Up @@ -8,6 +8,11 @@ en:

errors:
models:
bid:
permissions: 'You are not allowed to bid on this auction'
amount:
greater_than_max: 'Bids cannot be greater than the current max bid'
below_zero: 'Bid amount out of range'
user:
attributes:
duns_number:
Expand Down
2 changes: 1 addition & 1 deletion spec/controllers/bids_controller_spec.rb
Expand Up @@ -155,7 +155,7 @@
expect(flash[:bid]).to eq("success")
expect(response).to redirect_to("/auctions/#{auction.id}")

bid = auction.bids.order('created_at DESC').first
bid = auction.bids.last
expect(bid.bidder).to eq(current_bidder)
expect(bid.amount).to eq(1000)
expect(bid.via).to eq('web')
Expand Down
1 change: 0 additions & 1 deletion spec/factories/users.rb
Expand Up @@ -29,6 +29,5 @@
contracting_officer true
end
end

end
end
33 changes: 12 additions & 21 deletions spec/requests/bids_spec.rb
Expand Up @@ -95,7 +95,9 @@

it 'returns a json error' do
post auction_bids_path(auction), params, headers
expect(json_response['error']).to eq('Auction not available')
expect(json_response['error']).to eq(
'You are not allowed to bid on this auction'
)
end

it 'returns a 403 status code' do
Expand All @@ -120,7 +122,9 @@

it 'returns a json error' do
post auction_bids_path(auction), params, headers
expect(json_response['error']).to eq('Auction not available')
expect(json_response['error']).to eq(
'You are not allowed to bid on this auction'
)
end

it 'returns a 403 status code' do
Expand Down Expand Up @@ -286,7 +290,9 @@

it 'returns a json error' do
post auction_bids_path(auction), params, headers
expect(json_response['error']).to eq('You must have a valid SAM.gov account to place a bid')
expect(json_response['error']).to eq(
'You are not allowed to bid on this auction'
)
end

it 'returns a 403 status code' do
Expand All @@ -307,7 +313,9 @@

it 'returns a json error' do
post auction_bids_path(auction), params, headers
expect(json_response['error']).to eq('You must have a valid SAM.gov account to place a bid')
expect(json_response['error']).to eq(
'You are not allowed to bid on this auction'
)
end

it 'returns a 403 status code' do
Expand Down Expand Up @@ -364,23 +372,6 @@
end.to_not change { auction.bids.count }
end
end

context 'and the bid amount contains cents' do
let(:bid_amount) { 1.99 }

it 'returns a json error' do
post auction_bids_path(auction), params, headers
expect(json_response['error']).to eq('Bids must be in increments of one dollar')
end

it 'returns a 403 status code' do
post auction_bids_path(auction), params, headers
expect(status).to eq(403)
end

it 'should not create a bid' do
end
end
end
end
end

0 comments on commit 903fe73

Please sign in to comment.