Skip to content

Add manipulations to an Active Record scope to change the records when they are finally returned from the database

Notifications You must be signed in to change notification settings

adamcooke/records-manipulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Records Manipulator for ActiveRecord

This gem consists of a simple extention to Active Record to allow you to specify manipulations for an array of records before they are returned from the database.

For example, if we have a Post model and we wanted to do something to it when it was returned from our database, we might do this:

posts = Post.where(:published => true)
posts.each { |p| p.taint! }

That's fine but we had to define this at the end of our scope once we already had loaded the records from the array. This isn't very portable and doesn't allow any further chaining after you've made your changes.

With manipulate you can define a procedure to be executed when the records are actually returned from the database. You may wish to do this sort of thing with a presenter but sometimes that's overkill for a simple use case.

posts = Posts.where(:published => true).manipulate do |records|
  records.each { |p| p.taint! }
end

After this has run, we still haven't actually made any queries but when we do we know that the posts will have the taint! method executed on them.

For a slightly more complex example, you might use this to include custom (non-AR) data for one of your classes. Let's say we want to preload the biography for all the users in our app from the Twitter API. Our user model might look like this:

class User < ActiveRecord::Base
  def self.includes_twitter_bio
    manipulate do |records|
      # Get all our usernames for the records we're going to be rendering
      usernames = records.map(&:twitter_username)

      # Get the bios from the twitter API (this is psudocode). It accepts an array
      # of users and returns a hash of username to bio.
      author_bios = TwitterAPI.get_author_bios(author_usernames)

      # Add the bios to the users
      records.each do |user|
        user.instance_variable_set("@twitter_bio", author_bios[user.twitter_username])
      end
    end
  end

  def twitter_bio
    @twitter_bio ||= TwitterAPI.get_author_bio(self.twitter_username)
  end
end

Once you've added a method to your model, you can then easily use it wherever you want to pre-load this data. Here we're using it in combination with pagination. We'll only preload data for the users that are required for the requested page.

class UsersController < ApplicationController

  def index
    users = User.includes_twitter_bio.page(params[:page])
  end

end

Installation

gem 'records_manipulator'

About

Add manipulations to an Active Record scope to change the records when they are finally returned from the database

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages