<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DZone Snippets: activerecord code</title>
    <link>http://snippets.dzone.com/posts</link>
    <pubDate>Sat, 26 Jul 2008 00:08:43 GMT</pubDate>
    <description>DZone Snippets: activerecord code</description>
    <item>
      <title>Custom SQL query without find_by_sql</title>
      <link>http://snippets.dzone.com/posts/show/5570</link>
      <description>What if you need to call a custom query in Rails? In most cases you'll be content with ditching ActiveRecord::Base.find and going with .find_by_sql. But instantiating an Active Record per row is expensive. What if you want something faster, but you still want an OO feel? Pop this in your environment.rb (or a separate file) and give this a whirl:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# OO-ified connection.select_all&lt;br /&gt;require 'ostruct'&lt;br /&gt;module ActiveRecord&lt;br /&gt;  class Base&lt;br /&gt;    class &lt;&lt; self&lt;br /&gt;      def select_all(query)&lt;br /&gt;        rows = connection.select_all(query)&lt;br /&gt;        rows.map! do |row|&lt;br /&gt;          row = OpenStruct.new(row)&lt;br /&gt;          table = row.send(:table)&lt;br /&gt;          table.each {|k, v| table[k] = select_type_cast(v) }&lt;br /&gt;          row&lt;br /&gt;        end&lt;br /&gt;        rows&lt;br /&gt;      end&lt;br /&gt;      def select_one(query)&lt;br /&gt;        select_all(query).first&lt;br /&gt;      end&lt;br /&gt;      def select_value(query)&lt;br /&gt;        select_type_cast(connection.select_value(query))&lt;br /&gt;      end&lt;br /&gt;      def select_type_cast(v)&lt;br /&gt;        return unless v&lt;br /&gt;        if md = v.match(/^(\d{4})-(\d{2})-(\d{2})$/)&lt;br /&gt;          Date.new(*md.captures.map(&amp;:to_i)) rescue v&lt;br /&gt;        elsif md = v.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/)&lt;br /&gt;          Time.local(*md.captures.map(&amp;:to_i)) rescue v&lt;br /&gt;        elsif v =~ /^\d+$/&lt;br /&gt;          v.to_i&lt;br /&gt;        elsif v =~ /^\d+(?:\.\d+)+$/&lt;br /&gt;          v.to_f&lt;br /&gt;        else&lt;br /&gt;          v&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Mon, 02 Jun 2008 13:04:39 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/5570</guid>
      <author>mcmire ()</author>
    </item>
    <item>
      <title>Perform a Rails find() and iterate over the resulting records in groups</title>
      <link>http://snippets.dzone.com/posts/show/5461</link>
      <description>&lt;code&gt;&lt;br /&gt;module ActiveRecord&lt;br /&gt;  class Base&lt;br /&gt;    # This method lets you iterate over the results of a .find, in groups.&lt;br /&gt;    # (Basically an interface to LIMIT.)&lt;br /&gt;    # Anything you can pass as options to .find, you can pass here. &lt;br /&gt;    # Example 1:&lt;br /&gt;    #   Order.each_by(100, :conditions =&gt; { :cc_processed_at =&gt; nil }) do |order|&lt;br /&gt;    #     # do stuff with order&lt;br /&gt;    #   end&lt;br /&gt;    # Example 2:&lt;br /&gt;    #   Person.each_by(50, :order =&gt; 'name') do |person, index|&lt;br /&gt;    #     # do stuff with person and index&lt;br /&gt;    #   end&lt;br /&gt;    # Pass :update =&gt; true in the options to print a message before each group is&lt;br /&gt;    # fetched from the db.&lt;br /&gt;    #&lt;br /&gt;    # Author: Elliot Winkler &lt;elliot.winkler@gmail.com&gt;&lt;br /&gt;    # Source: http://snippets.dzone.com/posts/show/5461&lt;br /&gt;    def self.each_by(group_size, options={}, &amp;blk)&lt;br /&gt;      update = options.delete(:update) || false&lt;br /&gt;      num_records = count(options.except(:from))&lt;br /&gt;      return 0 if num_records == 0&lt;br /&gt;      #raise "Number of records: #{num_records}"&lt;br /&gt;      also_pass_offset = (blk.arity == 2)&lt;br /&gt;      0.step(num_records, group_size) do |offset|&lt;br /&gt;        find_options = { :offset =&gt; offset, :limit =&gt; group_size }.merge(options)&lt;br /&gt;        if update&lt;br /&gt;          if num_records == 1&lt;br /&gt;            puts "&gt;&gt; Reading the only record."&lt;br /&gt;          else&lt;br /&gt;            start_offset = offset + 1&lt;br /&gt;            end_offset   = offset + group_size&lt;br /&gt;            end_offset   = num_records if num_records &lt; end_offset&lt;br /&gt;            puts "&gt;&gt; Reading records #{start_offset}-#{end_offset}."&lt;br /&gt;          end&lt;br /&gt;        end &lt;br /&gt;        find(:all, find_options).each do |record|&lt;br /&gt;          also_pass_offset ? blk.call(record, offset) : blk.call(record)&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;      num_records&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Also see:&lt;br /&gt;&lt;br /&gt;* http://weblog.jamisbuck.org/2007/4/6/faking-cursors-in-activerecord&lt;br /&gt;* http://weblog.jamisbuck.org/2007/2/28/poor-man-s-pagination</description>
      <pubDate>Mon, 05 May 2008 15:35:43 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/5461</guid>
      <author>mcmire ()</author>
    </item>
  </channel>
</rss>
