Skip to content

Commit

Permalink
Merge pull request #310 from gocardless/issue-309
Browse files Browse the repository at this point in the history
Support ActiveRecord transitions which don't include Statesman::Adapters::ActiveRecordTransition
  • Loading branch information
Tim Rogers authored Feb 14, 2018
2 parents dbb3a75 + 42cdd84 commit 084ec3a
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 5 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ Order.not_in_state(:checking_out) # => [#<Order id: "123">]

By default Statesman stores transition history in memory only. It can be
persisted by configuring Statesman to use a different adapter. For example,
ActiveRecord within Rails:
for ActiveRecord within Rails:

`config/initializers/statesman.rb`:

Expand All @@ -137,6 +137,10 @@ Generate the transition model:
$ rails g statesman:active_record_transition Order OrderTransition
```

Your transition class should
`include Statesman::Adapters::ActiveRecordTransition` if you're using the
ActiveRecord adapter.

If you're using the ActiveRecord adapter and decide not to include the default
`updated_at` column in your transition table, you'll need to configure the
`updated_timestamp_column` option on the transition class, setting it to another column
Expand Down Expand Up @@ -178,8 +182,12 @@ or 5. To do that
t.json :metadata, default: {}
```

* Remove `include Statesman::Adapters::ActiveRecordTransition` statement from your
transition model
* Remove the `include Statesman::Adapters::ActiveRecordTransition` statement from
your transition model. (If you want to customise your transition class's "updated
timestamp column", as described above, you should define a
`.updated_timestamp_column` method on your class and return the name of the column
as a symbol, or `nil` if you don't want to record an updated timestamp on
transitions.)

## Configuration

Expand Down
17 changes: 15 additions & 2 deletions lib/statesman/adapters/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,28 @@ def transition_conflict_error?(e)
end

def with_updated_timestamp(params)
return params if @transition_class.updated_timestamp_column.nil?
# TODO: Once we've set expectations that transition classes should conform to
# the interface of Adapters::ActiveRecordTransition as a breaking change in the
# next major version, we can stop calling `#respond_to?` first and instead
# assume that there is a `.updated_timestamp_column` method we can call.
#
# At the moment, most transition classes will include the module, but not all,
# not least because it doesn't work with PostgreSQL JSON columns for metadata.
column = if @transition_class.respond_to?(:updated_timestamp_column)
@transition_class.updated_timestamp_column
else
ActiveRecordTransition::DEFAULT_UPDATED_TIMESTAMP_COLUMN
end

return params if column.nil?

timestamp = if ::ActiveRecord::Base.default_timezone == :utc
Time.now.utc
else
Time.now
end

params.merge(@transition_class.updated_timestamp_column => timestamp)
params.merge(column => timestamp)
end
end
end
Expand Down
13 changes: 13 additions & 0 deletions spec/statesman/adapters/active_record_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,19 @@
to(change { previous_transition.reload.updated_at })
end

context "for a transition class without an updated timestamp column attribute" do
let!(:adapter) do
described_class.new(MyActiveRecordModelTransitionWithoutInclude,
model,
observer)
end

it "defaults to touching the previous transition's updated_at timestamp" do
expect { Timecop.freeze(Time.now + 5.seconds) { create } }.
to(change { previous_transition.reload.updated_at })
end
end

context "with a custom updated timestamp column set" do
around do |example|
MyActiveRecordModelTransition.updated_timestamp_column.tap do |original_value|
Expand Down
7 changes: 7 additions & 0 deletions spec/support/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ class MyActiveRecordModelTransition < ActiveRecord::Base
serialize :metadata, JSON
end

class MyActiveRecordModelTransitionWithoutInclude < ActiveRecord::Base
self.table_name = "my_active_record_model_transitions"

belongs_to :my_active_record_model
serialize :metadata, JSON
end

class CreateMyActiveRecordModelMigration < MIGRATION_CLASS
def change
create_table :my_active_record_models do |t|
Expand Down

0 comments on commit 084ec3a

Please sign in to comment.