No commit activity in last 3 years
No release in over 3 years
Add manipulations to an Active Record scope to change the records when they are finally returned from the database
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

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'