Skip to content

Commit

Permalink
refector using state_machine
Browse files Browse the repository at this point in the history
  • Loading branch information
jasl committed Aug 18, 2013
1 parent e4eb9cb commit 03b4592
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 65 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ gem 'china_city'
gem 'alipay', github: 'chloerei/alipay'
gem 'priceable'
gem 'jbuilder'
gem 'state_machine'
gem 'ruby-graphviz', :require => 'graphviz'

group :pg do
gem 'pg', :platform => [:ruby, :mswin, :mingw]
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ GEM
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
ruby-graphviz (1.0.9)
rubyzip (0.9.9)
rvm-capistrano (1.4.3)
capistrano (>= 2.15.4)
Expand Down Expand Up @@ -349,6 +350,7 @@ GEM
sprockets (~> 2.8)
sqlite3 (1.3.7)
sqlite3 (1.3.7-x86-mingw32)
state_machine (1.2.0)
subexec (0.2.3)
tabs_on_rails (2.2.0)
temple (0.6.6)
Expand Down Expand Up @@ -440,6 +442,7 @@ DEPENDENCIES
rails-observers
rails-timeago
rspec-rails
ruby-graphviz
rvm-capistrano
sass-rails (~> 4.0.0)
selenium-webdriver
Expand All @@ -448,6 +451,7 @@ DEPENDENCIES
simplecov
slim-rails (~> 1.1.1)
sqlite3
state_machine
tabs_on_rails
thin (~> 1.5.0)
uglifier (>= 1.3.0)
Expand Down
1 change: 1 addition & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require 'tasks/state_machine'
require File.expand_path('../config/application', __FILE__)

NineteenWu::Application.load_tasks
3 changes: 3 additions & 0 deletions app/models/event_observer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ class EventObserver < ActiveRecord::Observer
def before_create(event)
save_group event
end

def after_create(event)
notify_followers event
event.tickets.create name: '门票', price: 0
Expand All @@ -26,10 +27,12 @@ def after_find(event)
end

private

def save_group(event)
group = event.user.groups.where(:slug => event.slug).first_or_create!
event.group = group
end

def notify_followers(event)
event.group.followers.each do |follower|
UserMailer.delay.notify_email follower, event
Expand Down
147 changes: 88 additions & 59 deletions app/models/event_order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class EventOrder < ActiveRecord::Base
end

before_create do
self.status = free? ? :paid : :pending
self.status = free? ? 'paid' : 'pending'
event.decrement! :tickets_quantity, self.quantity if event.tickets_quantity
end

Expand All @@ -30,70 +30,99 @@ def free?
self.price_in_cents.zero?
end

def pending?
self.status.to_sym == :pending
end

def paid?
self.status.to_sym == :paid
end

def canceled?
self.status.to_sym == :canceled
end

def request_refund?
self.status.to_sym == :request_refund
end

def complete_refund?
self.status.to_sym == :complete_refund
end

def can_pay?
pending? && !event.finished?
end

def can_cancel?
pending? && !event.finished?
end

def can_request_refund?
# TODO: can not refund if attended
paid? && (event.start_time - Time.now > 7.days)
end

def can_complete_refund?
request_refund?
end

def pay!(trade_no)
return false unless can_pay?

self.update_attributes status: 'paid', trade_no: trade_no
OrderMailer.delay.notify_user_paid(self)
OrderMailer.delay.notify_organizer_paid(self)
end
state_machine :status, :initial => :pending do
state :pending
state :paid, :request_refund, :complete_refund do
validates :trade_no, :presence => true
end

def cancel!
return false unless can_cancel?
event :pay do
transition :pending => :paid, :if => ->(order) { !order.event.finished? }
end

self.update_attributes status: 'canceled'
event.increment! :tickets_quantity, self.quantity if event.tickets_quantity
end
event :cancel do
transition :pending => :canceled, :if => ->(order) { !order.event.finished? }
end

def request_refund!
return false unless can_request_refund?
event :request_refund do
transition :paid => :request_refund, :if => ->(order) { order.event.start_time - Time.now > 7.days }
end

self.update_attributes status: 'request_refund'
event.increment! :tickets_quantity, self.quantity if event.tickets_quantity
event :complete_refund do
transition :request_refund => :complete_refund
end
end

def complete_refund!
return false unless can_complete_refund?

self.update_attributes status: 'complete_refund'
end
# override state_machine generated method to accept trade_no
def pay(trade_no)
self.trade_no = trade_no
super
end

#def pending?
# self.status.to_sym == :pending
#end
#
#def paid?
# self.status.to_sym == :paid
#end
#
#def canceled?
# self.status.to_sym == :canceled
#end
#
#def request_refund?
# self.status.to_sym == :request_refund
#end
#
#def complete_refund?
# self.status.to_sym == :complete_refund
#end
#
#def can_pay?
# pending? && !event.finished?
#end
#
#def can_cancel?
# pending? && !event.finished?
#end
#
#def can_request_refund?
# # TODO: can not refund if attended
# paid? && (event.start_time - Time.now > 7.days)
#end
#
#def can_complete_refund?
# request_refund?
#end
#
#def pay!(trade_no)
# return false unless can_pay?
#
# self.update_attributes status: 'paid', trade_no: trade_no
# OrderMailer.delay.notify_user_paid(self)
# OrderMailer.delay.notify_organizer_paid(self)
#end
#
#def cancel!
# return false unless can_cancel?
#
# self.update_attributes status: 'canceled'
# event.increment! :tickets_quantity, self.quantity if event.tickets_quantity
#end
#
#def request_refund!
# return false unless can_request_refund?
#
# self.update_attributes status: 'request_refund'
# event.increment! :tickets_quantity, self.quantity if event.tickets_quantity
#end
#
#def complete_refund!
# return false unless can_complete_refund?
#
# self.update_attributes status: 'complete_refund'
#end

def require_invoice
items.map(&:require_invoice).any?
Expand Down
15 changes: 15 additions & 0 deletions app/models/event_order_observer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
class EventOrderObserver < ActiveRecord::Observer
def after_pay(order, transition)
OrderMailer.delay.notify_user_paid( order)
OrderMailer.delay.notify_organizer_paid(order)
end

def after_cancel(order, transition)
order.event.increment! :tickets_quantity, order.quantity if order.event.tickets_quantity
end

def after_request_refund(order, transition)
order.event.increment! :tickets_quantity, order.quantity if order.event.tickets_quantity
end
end
2 changes: 1 addition & 1 deletion config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Application < Rails::Application

# Activate observers that should always be running.
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
config.active_record.observers = :event_observer
config.active_record.observers = :event_observer, :event_order_observer

# @see config/initializers/setup_locale.rb
# config.time_zone = 'Beijing'
Expand Down
10 changes: 5 additions & 5 deletions spec/models/event_order_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
end

describe '#pay' do
before { subject.pay!(trade_no) }
before { subject.pay(trade_no) }
context 'pending' do
its(:pending?) { should be_false }
its(:paid?) { should be_true }
Expand All @@ -86,7 +86,7 @@
end

describe 'cancel order' do
before { order.cancel! }
before { order.cancel }
subject { event }
its(:tickets_quantity) { should eql 400 }
end
Expand All @@ -96,14 +96,14 @@
order.pay!(trade_no)
end
subject { order }
its(:request_refund!) { should be_false }
its(:request_refund) { should be_false }
end

describe "request refund order back its ticket's quantity immediately" do
before do
event.update! start_time: 8.days.since, end_time: 9.days.since
order.pay!(trade_no)
order.request_refund!
order.pay(trade_no)
order.request_refund
end
subject { event }
its(:tickets_quantity) { should eql 400 }
Expand Down

0 comments on commit 03b4592

Please sign in to comment.