August 19th was Whyday, and to commemorate it, I decided to write a gem called activerecord-except
.
WHAT IS IT?
activerecord-except
is a Ruby gem that extends the functionality of ActiveRecord, allowing you to select all the fields from a table, except the ones that you specify. For example, if you have a table users.
development_db=# \d users
Table "public.users"
Column |
-------------------------------+-
id |
username |
password |
email |
first_name |
last_name |
phone |
...
created_at |
updated_at |
And you want to get all the fields except for the password, you’d have to pass each of them in your select clause like so
User.all.select(:id,
:username,
:email,
:first_name,
:last_name,
:phone,
...
:created_at,
:updated_at)
Instead, using activerecord-except
, can simplify your statement by saying only the field you don’t want, in this case, the password one
User.all.except(:password)
HOW DOES IT WORK?
Under the hood, the except
clause makes use of the traditional select
clause. So our previous example will produce the following query
SELECT "users"."id",
"users"."username",
"users"."first_name",
"users"."last_name",
"users"."phone",
"users"."created_at",
...
"users"."updated_at"
FROM "users"
This is because the SQL language doesn’t provide such functionality out of the box.
I don’t know what is the reason for this. I can only speculate that it’s to be more explicit and not be caught by surprise if a field in a table gets added/deleted/changed. However, *
is also wildly used. In Rails for example, it is what you get, when you don’t specify a select
clause in your query.
The way I managed to make it work is by adding a method toActiveRecord::Relation
which asks the model for all its attributes and rejecting those that match with the ones passed as arguments.
klass._default_attributes
.keys.map(&:to_sym)
.reject { |attr| fields.include?(attr) }
Note: As you can see, I’m using _default_attributes
which starts with an underscore. This can mean that the method is not intended to be relied upon.
Whether or not you might want to use in production, I leave up to you, where I really see the benefit of activerecord-except
is for writing one-off scripts to extract data, because it makes them much easier to read.
WANT TO GIVE IT A TRY?
You can install it from rubygems or you can check the source code either on Sourcehut or GitHub.