Thoughts on Engineering, Photography, and Design.

Hey, I'm Ryan Heath. I design & develop things for a living and play with cameras for fun. This is where I share my thoughts on all of that — and probably more — along the way.

Setting Ownership in Rails

There’s a common pattern in a lot of applications to track who did what. Who created this post? Who was the last person to update it? Maybe it’s for accountability, maybe it’s because your client is nosy.

There are gems for this, but it’s such a simple thing, that extra dependency isn’t really worth it. So let’s take a look at a pretty simple way to achieve this in Rails 7 using a concern:

 1module Ownership
 2  extend ActiveSupport::Concern
 3
 4  included do
 5    before_validation :set_ownership
 6
 7    scope :created_by, ->(user_id) {
 8      where(creator_id: user_id)
 9    }
10    scope :updated_by, ->(user_id) {
11      where(updater_id: user_id)
12    }
13
14    belongs_to :creator, class_name: 'User',
15      foreign_key: 'creator_id', optional: true
16    belongs_to :updater, class_name: 'User',
17      foreign_key: 'updater_id'
18
19    validates :creator_id, :updater_id,
20      presence: true
21  end
22
23  private
24
25  def set_ownership
26    current_user = Current.user
27
28    if new_record?
29      self.creator_id = current_user.id
30      self.updater_id = current_user.id
31    else
32      self.updater_id = current_user.id
33    end
34  end
35end

Now, for any model that has creator_id and updater_id columns, you just have to include the Ownership module:

 1class Post < ApplicationRecord
 2  include Ownership
 3
 4  # ...
 5end
 6
 7>> @post = Post.find(1)
 8>> @post.creator
 9# => #<User id: 10 ... >
10>> @post.updator
11# => #<User id: 20 ... >

And whenever a Post is created, the creator is automagically set; similarly, whenever any Post is updated, the updater is automagically set. This, of course, assumes your application has user sessions, since you obviously need to know who’s logged in doing the creating and updating.