In BrodyDNA I have a few models that are mostly represented by a JSON-backed column. I don’t want to deserialize the entire JSON payload every time that row is called — there are tens of millions of rows accessed every day on this little side project, and that’s a lot of CPU cycles. I make use of SQL aliases to pull the data that I went.

In one controller action, I have this:

@matches ="data->'test_guid' as test_guid, data->'public_display_name' as name, last_synced_at")

Fine, whatever. I have data->'test_guid' as test_guid a lot though and heaven forbid something changes in the data attribute I am left scrambling!

What I wanted was this:

@matches = @leed.leed_matches.with_test_guid.with_name.and_select("last_synced_at")

Or something.

Slight issue with ActiveRecord::QueryMethods


Only gets name and id is left in the dark.

So we need and_select, or something.

module ActiveRecord module QueryMethods def and_select(*fields) if(!select_values.any?) fields.unshift(arel_table[]) end select(*fields) end end end

The ActiveModel DSL

``` module ColumnAliases extend ActiveSupport::Concern

included do class_attribute :column_aliases, default: {} end

class_methods do def column_alias(name, sql) self.column_aliases[name] = Arel.sql(sql).as(name.to_s) scope “with_#{name}”.to_sym, -> { and_select(column_aliases[name]) } end end end ```


``` class Leed::Match < ApplicationRecord include ColumnAliases

column_alias :test_guid, “data->’test_guid’” column_alias :name, “data->’public_display_name’” end ```




My colleague and I were talking about how this could be improved. They mentioned we probably really want something like:, :name, :last_synced_at)

Which, we kind of can get, but not for things backed by SQL (at this time):

class Post < ApplicationRecord alias_attribute :subject, :title end

Post.where(subject: "bob") and Post.last.subject are both respectable.

I made a post on the mailing list: