module SimpleColumn
Purpose: Create dynamic modules which define dynamic methods for scopes based on a dynamic array of column names
Library Usage:
class Monkey < ActiveRecord::Base
include SimpleColumn::Scopes.new(:for_user_id, :for_seller_id, ... etc) # => for_user_id, and for_seller_id scopes are added to the model, and they query on the user_id and seller_id columns, respectively
Constants
- SCOPE_PREFIX
- SCOPE_PREFIX_REGEX
Public Class Methods
new(*scope_names)
click to toggle source
# File lib/simple_column/scopes.rb, line 34 def initialize(*scope_names) # => { :for_user_id => "user_id" } @simple_scope_names_hash = scope_names.map(&:to_sym).each_with_object({}) do |scope_name, memo| # method name definitions are best with symbols, and gsub only works on strings. memo[scope_name] = scope_name.to_s.sub(SimpleColumn::SCOPE_PREFIX_REGEX, '') end # Raising an error here is safe, because it will fail on boot if there is an implementation problem (early!) unless (bad_scopes = @simple_scope_names_hash.select { |scope_name, column_name| scope_name.to_s == column_name }).blank? bad_scope_names(bad_scopes) end end
to_mod(scope_names_hash)
click to toggle source
returns an anonymous (nameless) Module instance
# File lib/simple_column/scopes.rb, line 20 def to_mod(scope_names_hash) Module.new do scope_names_hash.each do |scope_name, column_name| # methods are defined at the instance level, so will become class methods when this module extends a class. define_method(scope_name) do |value| where(column_name => value) end end end end
Public Instance Methods
bad_scope_names(bad_scopes)
click to toggle source
# File lib/simple_column/scopes.rb, line 61 def bad_scope_names(bad_scopes) raise ArgumentError, "SimpleColumn::Scopes need to be named like #{SimpleColumn::SCOPE_PREFIX}<column_name>, but provided #{bad_scopes.keys}" end
included(base)
click to toggle source
# File lib/simple_column/scopes.rb, line 46 def included(base) # How to do this without breaking the build? # if ActiveRecord::Base.connection.active? # # Invoking this requires that a database be present. # unless (bad_scopes = @simple_scope_names_hash.reject { |_, column_name| base.column_names.include?(column_name) }).blank? # bad_scope_names(bad_scopes) # end # end anonymous_module = SimpleColumn.to_mod(@simple_scope_names_hash) # This will override methods defined in the including class with the same name, if any, # because extend has the effect of injecting the code into the bottom of the class file, lexically, # making these definitions highest priority. base.send(:extend, anonymous_module) end