'Create an ActiveRecord::Relation in rails 6 with a different table
I am trying to upgrade partitioned gem in order to use partitioning with Rails 6.1 (I am upgrading an existing Rails application).
I have managed to get everything to work, except for one part:
In partitioned gem, in order to query the partitioned table,
they would create a new relation with the "correct" arel_table (i.e - the actual partition table we want to query).
The following syntax worked with Rails 3.2:
def self.from_partition(*partition_key_values)
table_alias_name = partition_table_alias_name(*partition_key_values)
return ActiveRecord::Relation.new(self, self.arel_table_from_key_values(partition_key_values, table_alias_name))
end
Where self.arel_table_from_key_values(partition_key_values, table_alias_name)
is an instance of Arel::Table
pointing to the correct table name (partition).
I've updated the syntax to be:
def self.from_partition(*partition_key_values)
table_alias_name = partition_table_alias_name(*partition_key_values)
return ActiveRecord::Relation.new(self, table: self.arel_table_from_key_values(partition_key_values, table_alias_name))
end
The problem now is that when I try to run commands that worked in Rails 3.2 such as:
ItemLine.from_partition(11,1).find_by_code("1111")
I get errors such as undefined method `find_by_code' for #<ActiveRecord::Relation
Or if I try to run
ItemLine.from_partition(11,1).last
I get:
undefined local variable or method `implicit_order_column' for #<ActiveRecord::Relation
It seems like I am creating the relation in a wrong way.
What is the best/correct way to create an ActiveRecord::Relation
with a different arel table in Rails 6.1?
Thanks!
Solution 1:[1]
After digging around in the source code of ActiveRecord
,
I was able to solve it in the following way:
def self.from_partition(*partition_key_values)
table_alias_name = partition_table_alias_name(*partition_key_values)
table = self.arel_table_from_key_values(partition_key_values, table_alias_name)
tm = ActiveRecord::TableMetadata.new(self,table)
predicate_builder = ActiveRecord::PredicateBuilder.new(tm)
return ActiveRecord::Relation.create(self, table: table, predicate_builder: predicate_builder)
end
I still need to run some tests on this solution, but so far so good! :-)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Nikita Fedyashev |