Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert active record queries to ARel #416

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 22 additions & 17 deletions lib/statesman/adapters/active_record_queries.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def included(base)
query_builder = QueryBuilder.new(base, **@args)

base.define_singleton_method(:most_recent_transition_join) do
query_builder.most_recent_transition_join
query_builder.most_recent_transition_join.map(&:to_sql).join("")
end

define_in_state(base, query_builder)
Expand All @@ -67,7 +67,7 @@ def define_in_state(base, query_builder)
states = states.flatten

joins(most_recent_transition_join).
where(query_builder.states_where(states), states)
where(query_builder.in_state_conditions(states))
end
end

Expand All @@ -76,7 +76,7 @@ def define_not_in_state(base, query_builder)
states = states.flatten

joins(most_recent_transition_join).
where("NOT (#{query_builder.states_where(states)})", states)
where(query_builder.in_state_conditions(states).not)
end
end
end
Expand All @@ -92,23 +92,24 @@ def initialize(model, transition_class:, initial_state:,
@transition_name = transition_name
end

def states_where(states)
def most_recent_transition_join
table.
join(transition_table, Arel::Nodes::OuterJoin).
on(transition_table[transition_reflection.foreign_key].eq(table[:id]).
and(transition_table[:most_recent].eq(true))).
join_sources
end

def in_state_conditions(states)
if initial_state.to_s.in?(states.map(&:to_s))
"#{most_recent_transition_alias}.to_state IN (?) OR " \
"#{most_recent_transition_alias}.to_state IS NULL"
transition_table[:to_state].in(states).
or(transition_table[:to_state].eq(nil))
else
"#{most_recent_transition_alias}.to_state IN (?) AND " \
"#{most_recent_transition_alias}.to_state IS NOT NULL"
transition_table[:to_state].in(states).
and(transition_table[:to_state].not_eq(nil))
end
end

def most_recent_transition_join
"LEFT OUTER JOIN #{model_table} AS #{most_recent_transition_alias} " \
"ON #{model.table_name}.id = " \
"#{most_recent_transition_alias}.#{model_foreign_key} " \
"AND #{most_recent_transition_alias}.most_recent = #{db_true}"
end

private

attr_reader :model, :transition_class, :initial_state
Expand Down Expand Up @@ -140,8 +141,12 @@ def most_recent_transition_alias
"most_recent_#{transition_name.to_s.singularize}"
end

def db_true
::ActiveRecord::Base.connection.quote(true)
def transition_table
transition_class.arel_table.alias(most_recent_transition_alias)
end

def table
model.arel_table
end
end
end
Expand Down