1

Using aasm statemachine for model Booking.

The state machine have below states

 state :payment_authorized
 state :payment_captured
 state :payment_failed
 state :some_more_states

So to fetch bookings based on state I can call booking.payment_authorized. But what am looking for is I want all records with state payment_authorized and payment_captured.

This works booking.payment_authorized + booking.payment_captured but this is doing 2 database calls. one for finding authorized_state and other for captured_state. How can I do this more efficiently(in one call)?

Thank you

Abhilash
  • 2,864
  • 3
  • 33
  • 67
  • wouldn't `booking.payment_authorised` change the state of booking to 'payment_authorized' rather than checking it? Do you mean, `booking.payment_authorized?` – kiddorails Oct 24 '17 at 19:03
  • Yes, typo is fixed.. It will change. But there is a scenario where I need to fetch all records satisfying those two states... – Abhilash Oct 24 '17 at 19:06

2 Answers2

2

You can use Booking.payment_authorized.or(Booking.payment_captured) to get all records in a single query.

Tom Copeland
  • 1,221
  • 10
  • 10
2

@Tom gave a pretty good solution for the problem. It utilizes ActiveRelation's OR for logical union of two relations. Note that the solution is specific to Rails 5.

You can also do it via:

Booking.where(aasm_state: [:payment_authorized, :payment_captured])

aasm uses aasm_state column to contain the state, by default. It will make the IN query.

kiddorails
  • 12,961
  • 2
  • 32
  • 41
  • Thank you for the explanation. This method works and easy to chain using scopes. – Abhilash Oct 24 '17 at 19:39
  • 1
    @Abhilash: Rails scoping will work with `OR` as well, since resultant of ActiveRelation is a Relation which can be chained. The slight advantage is how SQL queries `IN`(sorts and binary search) over `OR`(goes for all row by row). – kiddorails Oct 24 '17 at 19:41
  • Never used scopes with OR before. Thank you for the info. – Abhilash Oct 24 '17 at 19:53