Skip to content

Commit

Permalink
Allow timestamp to accept an array of timestamps
Browse files Browse the repository at this point in the history
  • Loading branch information
atomaka committed Sep 21, 2016
1 parent b86deb9 commit 3799355
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 16 deletions.
18 changes: 14 additions & 4 deletions .todo.reek
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@ DuplicateMethodCall:
- ActiveModel::Transitions#read_state
- ActiveModel::Transitions#reload
- ActiveModel::Transitions#set_initial_state
- ActiveModel::Transitions#set_initial_state
- Transitions::Event#error_message_for_invalid_transitions
- Transitions::Event#fire
- Transitions::Event#fire
- Transitions::Event#initialize
- Transitions::Event#initialize
- Transitions::Event#update
- Transitions::Machine#handle_event_success_callback
- Transitions::Machine#handle_event_success_callback
- Transitions::Machine#initial_state
- Transitions::State#define_state_query_method
IrresponsibleModule:
Expand Down Expand Up @@ -46,6 +42,19 @@ FeatureEnvy:
- Transitions::Event#can_execute_transition_from_state?
- Transitions::Event#default_timestamp_name
- Transitions::Event#error_message_for_invalid_transitions
InstanceVariableAssumption:
exclude:
- Transitions::Event
- Transitions::Machine
- Transitions::State
ManualDispatch:
exclude:
- Transitions::Event#default_timestamp_name
- Transitions::Machine#fire_event
- Transitions::Machine#handle_event_failed_callback
- Transitions::Machine#handle_event_fired_callback
- Transitions::Machine#include_scopes
- Transitions::StateTransition#perform_guard
NestedIterators:
exclude:
- Transitions::Event#build_success_callback
Expand All @@ -56,6 +65,7 @@ TooManyInstanceVariables:
- Transitions::StateTransition
TooManyStatements:
exclude:
- initialize
- Transitions::Event#build_success_callback
- Transitions::Event#fire
- Transitions::Machine#fire_event
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ corresponding discussion).
If you'd like to note the time of a state change, Transitions comes with
timestamps free! To activate them, simply pass the `timestamp` option to the
event definition with a value of either true or the name of the timestamp
column. *NOTE - This should be either true, a String or a Symbol*
column. *NOTE - This should be either true, a String, a Symbol, or an Array of
these*
```ruby
# This will look for an attribute called exploded_at or exploded_on (in that order)
# If present, it will be updated
Expand Down
27 changes: 16 additions & 11 deletions lib/transitions/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def initialize(machine, name, options = {}, &block)
@machine = machine
@name = name
@transitions = []
@timestamps = []
if machine
machine.klass.send(:define_method, "#{name}!") do |*args|
machine.fire_event(name, self, true, *args)
Expand Down Expand Up @@ -67,29 +68,33 @@ def ==(other)

# Has the timestamp option been specified for this event?
def timestamp_defined?
!@timestamp.nil?
!@timestamps.nil?
end

def update(options = {}, &block)
@success = build_success_callback(options[:success]) if options.key?(:success)
self.timestamp = options[:timestamp] if options[:timestamp]
self.timestamp = Array(options[:timestamp]) if options[:timestamp]
instance_eval(&block) if block
self
end

# update the timestamp attribute on obj
def update_event_timestamp(obj, next_state)
obj.send "#{timestamp_attribute_name(obj, next_state)}=", Time.now
@timestamps.each do |timestamp|
obj.public_send "#{timestamp_attribute_name(obj, next_state, timestamp)}=", Time.now
end
end

# Set the timestamp attribute.
# @raise [ArgumentError] timestamp should be either a String, Symbol or true
def timestamp=(value)
case value
when String, Symbol, TrueClass
@timestamp = value
else
fail ArgumentError, 'timestamp must be either: true, a String or a Symbol'
def timestamp=(values)
values.each do |value|
case value
when String, Symbol, TrueClass
@timestamps << value
else
fail ArgumentError, 'timestamp must be either: true, a String or a Symbol'
end
end
end

Expand All @@ -98,8 +103,8 @@ def timestamp=(value)
# Returns the name of the timestamp attribute for this event
# If the timestamp was simply true it returns the default_timestamp_name
# otherwise, returns the user-specified timestamp name
def timestamp_attribute_name(obj, next_state)
timestamp == true ? default_timestamp_name(obj, next_state) : @timestamp
def timestamp_attribute_name(obj, next_state, user_timestamp)
user_timestamp == true ? default_timestamp_name(obj, next_state) : user_timestamp
end

# If @timestamp is true, try a default timestamp name
Expand Down
14 changes: 14 additions & 0 deletions test/active_record/test_active_record_timestamps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ def self.up
create_table(:orders, force: true) do |t|
t.string :state
t.string :order_number
t.datetime :processed_at
t.datetime :paid_at
t.datetime :prepared_on
t.datetime :dispatched_at
Expand Down Expand Up @@ -50,6 +51,11 @@ class Order < ActiveRecord::Base
transitions from: [:placed, :paid, :prepared], to: :cancelled
end

# should set cancellation_date
event :autocancel, timestamp: [:cancellation_date, :processed_at] do
transitions from: :paid, to: :cancelled
end

# should raise an exception as there is no timestamp col
event :reopen, timestamp: true do
transitions from: :cancelled, to: :opened
Expand Down Expand Up @@ -111,6 +117,14 @@ def create_order(state = nil)
assert_not_nil @order.cancellation_date
end

test 'moving to cancelled should set cancellation_date' do
@order = create_order(:paid)
@order.autocancel!
@order.reload
assert_not_nil @order.cancellation_date
assert_not_nil @order.processed_at
end

test 'moving to reopened should raise an exception as there is no attribute' do
@order = create_order(:cancelled)
assert_raise(NoMethodError) { @order.re_open! }
Expand Down

0 comments on commit 3799355

Please sign in to comment.