0.0
No release in over 3 years
ActionScope provides a comprehensive set of dynamic scopes for ActiveRecord models, including basic column filtering, text matching, range queries, association scopes, multi-column search, and sorting capabilities. Automatically generates scopes based on model attributes and associations.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 13.0
~> 3.0
~> 1.0

Runtime

 Project Readme

ActionScope

ActionScope provides a comprehensive set of dynamic scopes for ActiveRecord models, including basic column filtering, text matching, range queries, association scopes, multi-column search, and sorting capabilities. Automatically generates scopes based on model attributes and associations.

Features

  • Basic Scopes: Automatic by_column_name scopes for all model attributes
  • Text Matching: Fuzzy search scopes for string/text columns
  • Range Queries: Greater than, less than, and between scopes for numeric/date columns
  • Association Scopes: Automatic scopes for model associations
  • Multi-Column Search: Search across multiple columns with a single query
  • Sorting: Dynamic sorting scopes for all columns
  • Type-Aware: Automatically detects column types and generates appropriate scopes
  • Rails 7+ Compatible: Works with modern Rails versions

Installation

Add this line to your application's Gemfile:

gem 'action_scope'

And then execute:

bundle install

Or install it yourself as:

gem install action_scope

Usage

Basic Setup

Include ActionScope in your ActiveRecord models and call action_scope:

class User < ApplicationRecord
  include ActionScope
  
  action_scope
  
  # Your model code here...
end

Example Model

Let's say you have a User model with the following structure:

# db/migrate/xxx_create_users.rb
class CreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.text :bio
      t.integer :age
      t.decimal :salary, precision: 10, scale: 2
      t.datetime :last_login_at
      t.date :birth_date
      t.boolean :active
      t.references :company, null: false, foreign_key: true
      
      t.timestamps
    end
  end
end

# app/models/user.rb
class User < ApplicationRecord
  include ActionScope
  
  belongs_to :company
  has_many :posts
  
  action_scope
end

# app/models/company.rb
class Company < ApplicationRecord
  include ActionScope
  
  has_many :users
  
  action_scope
end

Generated Scopes

ActionScope automatically generates the following types of scopes:

1. Basic Scopes (by_column_name)

For every column in your model:

# Filter by exact values
User.by_name("John Doe")
User.by_email("john@example.com")
User.by_age(30)
User.by_active(true)

# Chain multiple filters
User.by_name("John").by_active(true).by_age(30)

2. Text Matching Scopes (by_column_name_match)

For string and text columns:

# Fuzzy search (uses LIKE %query%)
User.by_name_match("john")      # Finds "John Doe", "Johnny", etc.
User.by_email_match("gmail")    # Finds emails containing "gmail"
User.by_bio_match("developer")  # Searches bio text

3. Range Scopes

For numeric, date, and datetime columns:

# Greater than / Less than
User.by_age_gt(25)              # age > 25
User.by_age_gte(25)             # age >= 25
User.by_age_lt(65)              # age < 65
User.by_age_lte(65)             # age <= 65

# Date ranges
User.by_birth_date_gte(Date.new(1990, 1, 1))
User.by_last_login_at_lt(1.week.ago)

# Salary ranges
User.by_salary_gte(50000)
User.by_salary_lte(100000)

# Chain range conditions
User.by_age_gte(25).by_age_lte(65)  # Between 25 and 65

4. Association Scopes

For belongs_to and has_many associations:

# Filter by association ID
User.by_company(1)              # Users belonging to company with ID 1
User.by_company(company)        # Users belonging to company object

# Works with company model too
Company.by_user(user)           # Companies associated with user

5. Multi-Column Search

Search across multiple columns simultaneously:

# Searches name, email, bio, and id columns
User.by_search_query("john")

# Finds users where any searchable column contains "john"
User.by_search_query("developer")  # Matches name, email, or bio

6. Sorting Scopes

For all columns:

# Sort ascending (default)
User.sort_by_name
User.sort_by_age
User.sort_by_created_at

# Sort descending
User.sort_by_name('desc')
User.sort_by_salary('desc')

# Generic sorting method
User.sorted_by(:name, 'asc')
User.sorted_by(:age, 'desc')

Advanced Usage

Selective Scope Generation

Generate scopes only for specific columns:

class User < ApplicationRecord
  include ActionScope
  
  # Only generate scopes for name and email
  action_scope :name, :email
end

Excluding Columns

Exclude certain columns from scope generation:

class User < ApplicationRecord
  include ActionScope
  
  # Generate scopes for all columns except password_digest
  action_scope except: [:password_digest, :secret_token]
end

Custom Configuration

You can also provide a block for custom configuration:

class User < ApplicationRecord
  include ActionScope
  
  action_scope do |model|
    # Custom logic here
    puts "Generating scopes for #{model.name}"
  end
end

Real-World Examples

Building Complex Queries

# Find active adult users from a specific company with recent activity
User.by_active(true)
    .by_age_gte(18)
    .by_company(company)
    .by_last_login_at_gte(1.month.ago)
    .sort_by_name

# Search for users and sort by salary
User.by_search_query("engineer")
    .by_salary_gte(70000)
    .sort_by_salary('desc')

# Filter by date ranges
User.by_birth_date_gte(Date.new(1980, 1, 1))
    .by_birth_date_lte(Date.new(2000, 12, 31))
    .by_active(true)

Scope Introspection

ActionScope provides methods to inspect generated scopes:

action_scope_options - Complete Scope Overview

The action_scope_options method (aliased as options_for_search) returns a comprehensive hash of all available scopes with their types and options:

User.action_scope_options
# Returns a hash like this:

{
  # Basic scopes with column types
  :by_name => nil,
  :by_email => nil, 
  :by_bio => nil,
  :by_age => nil,
  :by_salary => nil,
  :by_last_login_at => nil,
  :by_birth_date => nil,
  :by_active => nil,
  :by_company_id => nil,
  
  # Text matching scopes for string/text columns
  :by_name_match => nil,
  :by_email_match => nil,
  :by_bio_match => nil,
  
  # Multi-column search with searchable columns
  :by_search_query => [
    "id", "name", "email", "bio", "age", "salary", 
    "last_login_at", "birth_date", "active", "company_id"
  ],
  
  # Range scopes for numeric/date columns
  :by_age_gte => :integer,
  :by_age_lte => :integer, 
  :by_age_gt => :integer,
  :by_age_lt => :integer,
  :by_salary_gte => :decimal,
  :by_salary_lte => :decimal,
  :by_salary_gt => :decimal,
  :by_salary_lt => :decimal,
  :by_last_login_at_gte => :datetime,
  :by_last_login_at_lte => :datetime,
  :by_last_login_at_gt => :datetime,
  :by_last_login_at_lt => :datetime,
  :by_birth_date_gte => :date,
  :by_birth_date_lte => :date,
  :by_birth_date_gt => :date,
  :by_birth_date_lt => :date,
  
  # Association scopes
  :by_company => "id",
  
  # Sorting scopes
  :sort_by_name => ["asc", "desc"],
  :sort_by_email => ["asc", "desc"],
  :sort_by_age => ["asc", "desc"],
  :sort_by_salary => ["asc", "desc"],
  :sort_by_created_at => ["asc", "desc"]
}

Individual Introspection Methods

You can also access specific scope types individually:

# Basic scopes with their column types
User.basic_scopes_with_types

# Text matching scopes  
User.matchable_scopes_with_types

# Range scopes with their column types
User.rangeable_scopes_scopes_with_types

# Sorting scopes with available directions
User.sortable_scopes_with_directions

# Association scopes with their primary keys
User.association_scopes_with_primary_keys

# Multi-search scope with searchable column names
User.multi_searchable_scopes_with_column_names

This introspection is particularly useful for building dynamic UIs, API documentation, or debugging scope availability.