Search code examples
ruby-on-railsruby-on-rails-4activerecordnested-resourcespaper-trail-gem

Rails 4 x paper_trail: filter versions by item_id with nested resources


In my Rails 4 app, I have the following models:

class User < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :calendars, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
end

class Post < ActiveRecord::Base
    belongs_to :calendar
end

I installed the paper_trail gem to track changes on my post model as explained in the documentation and it works like a charm.

Versions are displayed in the Calendars#Index view, which serves as a dashboard to the user.

Here is how my CalendarsController is setup:

def index
  @user = current_user
  @calendars = @user.calendars.all
  @comments = @user.calendar_comments.order("created_at DESC").limit(20)
  @versions = PaperTrail::Version.order('id DESC').limit(10)
end

As you may infer from the above code, the problem is that ALL versions (at least the last 10 versions) from the database are pulled, regardless of which post they are related to (and most importantly, whether this post belong_to a calendar that belong_to the current_user, or not).

However, what we want is to assign to @versions:

  • All the versions related to
  • All the posts from
  • All the calendars that belong to
  • @user

I am thinking of creating an array of all the relevant posts ids and store it into @posts and then store in @versions all the versions where the id is included in the @posts array.

But this seems heavy and not consistent with the Rails way of doing things.

Any idea about how I should proceed?


Solution

  • You can make use of object's attributes, provided by PaperTrail (item_type and item_id):

    PaperTrail::Version
      .where(item_type: 'Post', item_id: Post.where(calendar_id: @calendars.ids))
      .order('id DESC')
      .limit(10)