From 4f04c2f561ec7cc3b900d5902f8a3e17c92cfad2 Mon Sep 17 00:00:00 2001 From: dmitry Date: Wed, 4 Nov 2020 21:20:11 +0200 Subject: [PATCH] Convert active record queries to ARel --- .../adapters/active_record_queries.rb | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/lib/statesman/adapters/active_record_queries.rb b/lib/statesman/adapters/active_record_queries.rb index d39d7bd5..f74e82b4 100644 --- a/lib/statesman/adapters/active_record_queries.rb +++ b/lib/statesman/adapters/active_record_queries.rb @@ -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) @@ -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 @@ -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 @@ -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 @@ -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