I have an application where I have a lot of JSON-backed columns. I do a lot of this:
Leed::Match.select("data->'test_guid' as guid, data->'public_display_name' as name, last_synced_at")
Fine, whatever. I can DRY this up with a monkeypatch to QueryMethods and some scopes:
module ActiveRecord
module QueryMethods
def and_select(*fields)
if(!select_values.any?)
fields.unshift(arel_table[Arel.star])
end
select(*fields)
end
end
end
scope :with_guid, -> { and_select(Arel.sql("data->'test_guid'").as("guid")) }
scope :with_name, -> { and_select(Arel.sql("data->'public_display_name'").as("name")) }
And then call:
Leed::Match.with_guid.with_name.and_select(:last_synced_at)
Okay, still “fine”, but, we have alias_attribute
from ActiveModel
, where I can normally:
class Post < ApplicationRecord
alias_attribute :subject, :title
end
And ActiveRecord::QueryMethods
respects those: rails/query_methods.rb at 7-0-stable · rails/rails · GitHub, rails/query_methods.rb at 7-0-stable · rails/rails · GitHub
Because of how they’re generated: rails/attribute_methods.rb at 7-0-stable · rails/rails · GitHub
However, because of how they’re generated, I obviously can’t:
alias_attribute :guid, Arel.sql("data->'test_guid'")
Would core accept a PR which, effectively (one way or another) allows for this? I don’t know if I’d want to match those methods, or if I’d want a completely separate:
class Leed::Match < ApplicationRecord
as_alias_attribute :guid, Arel.sql("data->'test_guid'")
as_alias_attribute :name, Arel.sql("data->'public_display_name'")
end
Whatever it is, I’d like to be able to:
Leed::Match.select(:guid)
and,
Leed::Match.where(guid: "1234")
At least, I think I do want to?
Whether or not it’s baked into alias_attribute
— I don’t know. But I’ve always been surprised we don’t have a way to better handle SQL aliasing in ActiveRecord. Maybe I’ve missed something for the last 10 years. I don’t know.