Skip to content

Instantly share code, notes, and snippets.

@foca
Created February 24, 2012 17:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save foca/1902096 to your computer and use it in GitHub Desktop.
Save foca/1902096 to your computer and use it in GitHub Desktop.
[FIXED] Help me clean this up so one scope uses the other!
# FIXED: This is what I did in the end, after discussing it with @dcadenas.
# Check the previous versions of the gist to see how the problem looked before :)
#
# I have this AR model that has two scopes that should return complementary sets
# of rows: one returns all the rows that match certain conditions, the other
# returns all rows that DON'T match the same conditions.
#
# I would like to build the second scope using the first one. Something like:
#
# class Article
# def self.problematic
# not(complete)
# end
# end
#
# For now the conditions are simple enough (just check for NULL/NOT NULL), but
# it's probable that I might need some more complex conditions in the future
# (like published_on < Time.current, since our scraper sometimes messes up).
#
# So this scope will become more complex, and I would like to avoid having to
# duplicate all the logic between both scopes.
#
# After poking around ARel's source code for a while I didn't find an easy way
# to do this. How would you approach this?
class Article < ActiveRecord::Base
# Public: Filter out articles that don't have all the information required for
# us to show them in the store/reader.
#
# Returns an ActiveRecord::Relation.
def self.complete
where(_conditions_for_complete)
end
# Public: Filter articles that don't have all the information required for us
# to show them in the store. This is the opposite of Article.complete.
#
# Returns an ActiveRecord::Relation.
def self.problematic
where(_conditions_for_complete.not)
end
# ARel conditions to filter articles that are complete or not. This can be
# later negated to compose both .complete and .problematic scopes.
#
# Returns an Arel::Node.
def self._conditions_for_complete
conditions = [:published_on, :title, :text, :url].map do |field|
arel_table[field].not_eq(nil)
end
conditions.inject(:and)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment