unscoping doesn't work with Arel Nodes as an argument if a symbol is used for the attribute identifier.
s = Model.arel_table['id'].lteq(5) # <= attribute identified with string, not symbol
s.class
=> Arel::Nodes::LessThanOrEqual
(r = Model.where(s)).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (\"models\".\"id\" <= 5)"
(r2 = r.unscope(where: s)).to_sql
=> "SELECT \"models\".* FROM \"models\""
Note: there's nothing magical about unscoping with the Arel Node as the arg, the more basic string or symbol work as well
(r2 = r.unscope(where: 'id')).to_sql
=> "SELECT \"models\".* FROM \"models\""
r2 = r.unscope(where: :id)
=> "SELECT \"models\".* FROM \"models\""
s = Model.arel_table[:id].lteq(5) # <= attribute identified with symbol, not string
(r = Model.where(s)).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (\"models\".\"id\" <= 5)"
(r2 = r.unscope(where: s)).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (\"models\".\"id\" <= 5)"
Note: there's nothing magical about unscoping with the Arel Node as the arg, the more basic string or symbol don't work either
(r2 = r.unscope(where: 'id')).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (\"models\".\"id\" <= 5)"
r2 = r.unscope(where: :id)
=> "SELECT \"models\".* FROM \"models\" WHERE (\"models\".\"id\" <= 5)"
# active_record/relation/query_methods.rb#906
def where_unscoping(target_value)
target_value = target_value.to_s #<= SOURCE, exhibit A
where_values.reject! do |rel|
case rel
when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThanOrEqual
subrelation = (rel.left.kind_of?(Arel::Attributes::Attribute) ? rel.left : rel.right)
subrelation.name == target_value #<= SOURCE, exhibit B, will never match a symbol name introduced by an Arel::Node
end
end
bind_values.reject! { |col,_| col.name == target_value }
end
Unscoping doesn't work with certain Arel Node types (LessThan shown here)
s = Model.arel_table['id'].lt(5)
(r = Model.where(s)).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (\"models\".\"id\" < 5)"
(r2 = r.unscope(where: s)).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (\"models\".\"id\" < 5)"
# active_record/relation/query_methods.rb#906
def where_unscoping(target_value)
target_value = target_value.to_s
where_values.reject! do |rel|
case rel
when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThanOrEqual
# ^^^ SOURCE: e.g. Arel::Nodes::LessThan is not present in this list
subrelation = (rel.left.kind_of?(Arel::Attributes::Attribute) ? rel.left : rel.right)
subrelation.name == target_value
end
end
bind_values.reject! { |col,_| col.name == target_value }
end
unscoping doesn't work when array or string where
args are used
(r = Model.where('id < ?', 5)).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (id < 5)"
(r2 = r.unscope(where: s)).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (id < 5)"
(r = Model.where('id < 5')).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (id < 5)"
(r2 = r.unscope(where: s)).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (id < 5)"
Only Arel::Node classes are compared for the rejection
# active_record/relation/query_methods.rb#906
def where_unscoping(target_value)
target_value = target_value.to_s
where_values.reject! do |rel|
case rel
when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThanOrEqual
# ^^^ SOURCE: e.g. only arel classes are compared for rejection
subrelation = (rel.left.kind_of?(Arel::Attributes::Attribute) ? rel.left : rel.right)
subrelation.name == target_value
end
end
bind_values.reject! { |col,_| col.name == target_value }
end
wip: