BetterPluck

BetterPluck adds pluck_with_methods and pluck_with_display_name to ActiveRecord. These methods allow you to pluck not only database columns but also virtual methods and association data, returning lightweight Struct objects instead of heavy ActiveRecord instances.

This approach can reduce memory usage by up to 3-20x compared to loading full ActiveRecord objects.

Primary purpose: to be used in huge form dropdowns for select inputs.

Installation

Add this line to your application's Gemfile:

gem 'better_pluck'

And then execute:

$ bundle install

Usage

Basic usage

You can pluck database columns and instance methods:

# Assuming Article has a method :name_on_site
articles = Article.pluck_with_methods(:id, :name, :email, :name_on_site)

articles.first.id           # => 1
articles.first.name_on_site  # => "My Article" (virtual method)

Associations

You can also pluck data from nested associations:

articles = Article.pluck_with_methods(
  :id,
  :name,
  author: [:name, :email, :display_name]
)

articles.first.author.email        # => "author@example.com"
articles.first.author.display_name # => "John Doe"

Pluck with Display Name

A convenience method specifically for dropdown lists and collections:

# Automatically includes :display_name for the model and associations
articles = Article.pluck_with_display_name(:id, :name, author: [:name, :email])

articles.first.display_name         # => "Article Name"
articles.first.author.display_name # => "Author Name <author@example.com>"

How it works

  1. Parsing: It parses the requested fields to distinguish between database columns, methods, and associations.
  2. Joining: It automatically applies left_joins for requested associations.
  3. Plucking: It uses the standard ActiveRecord pluck to fetch only the required database columns.
  4. Struct Generation: It creates a Struct class (cached for performance) and injects the source code of requested instance methods into it.
  5. Instantiation: It maps the raw data into these Struct objects.

Requirements

  • ActiveRecord >= 6.0
  • method_source
  • concurrent-ruby