gocardless / statesman

A statesmanlike state machine library.
https://gocardless.com/blog/statesman/
MIT License
1.78k stars 163 forks source link

Move #most_recent_transition_join to be a public method #330

Closed adambutler closed 6 years ago

adambutler commented 6 years ago

ActiveRecord's #or method requires that both sides of the query must have a compatible structure as such:

User.joins(:profile).where(name: "John").or(User.where(name: "Tom")).count
# => ArgumentError: Relation passed to #or must be structurally compatible. Incompatible values: [:joins]

User.joins(:profile).where(name: "John").or(User.joins(:profile).where(name: "Tom")).count
# => 2

The #in_state and #not_in_state methods of statesman chain the #joins and the #where calls together. This makes a query with ActiveRecord #or.

For example the following would produce an error since the query does not also include the #joins

class Store < ActiveRecord::Base
  # ...
  scope :belongs_to_user, -> (user) { where(user: user) }
  # ...
end

Post.in_state(:published).or(Post.belongs_to_user(current_user))

With this change the #most_recent_transition_join method is exposed meaning that the following query could be possible resolving the issue:

Post
  .in_state(:published)
  .or(Post.most_recent_transition_join.belongs_to_user(current_user))

Further instances and resources relating to this issue can be found at:

https://github.com/varvet/pundit/issues/440#issuecomment-277204775

http://codeatmorning.com/rails-5-meet-the-active-record-or-query/