Search code examples
ruby-on-railsactiverecordpolymorphic-associations

Scope to filter records with at least 3 "recent" polymorphic associations


I am working on a rails4 application that has Publication, Observation and Species models, of which the records can be "validated" by users (Devise User model) through a polymorphic association (Validation model).

Publications (and their metadata through associated HABTM models) are considered "validated" if the publication is validated by at least three users since the publication was last updated (i.e. validation.updated_at >= publication.updated_at for at least 3 validations). This criteria is implemented so that if information on the publication changes after being validated by users, those specific "outdated" validations are not counted, until revalidated by the user (through a touch on the association).

I am trying to figure out how I can produce a scope :validated and scope :unvalidated for the Publication model (i.e. filtering only the publications that are validated).

class Publication < ActiveRecord::Base
  has_and_belongs_to_many :users        // authors of that publication
  has_many :validations, as: :validatable
  has_many :validation_users, through: :validations, source: :user
 end

class Validation < ActiveRecord::Base
  belongs_to :validatable, polymorphic: true
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :validations
end

I can retrieve Publications with at least 3 validations like below (similar to this) - however how could I best retrieve (preferably as a scope) only those with at least 3 validations updated after the last update of the publication?

Publication.select("publications.*, count(validations.id) as validations_count").joins(:validations).group("publications.id").having("validations_count > 2")

Solution

  • You just need to add the mentioned condition:

    Publication.
      select("publications.*, count(validations.id) as validations_count").
      joins(:validations).
      where("validations.updated_at >= publications.updated_at").
      group("publications.id").
      having("validations_count > 2")