Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

« Newer Snippets
Older Snippets »
Showing 1-10 of 443 total  RSS 

Move acts_as_attachment / attachment_fu images

Use this to move files from the old directory structure (before 0000 format) to new one

Dir.new(File.dirname($PROGRAM_NAME)).each do |f|
  next if f == '0000' || f == 'move.rb' || f == '..' || f == '.'
  
  new_name = sprintf("%04d", f.to_i)
  
  puts "Moving #{f} to #{new_name}"
  puts `mv #{f} 0000/#{name}`
end

Deploying on a passenger / mod_rails host with capistrano

// add this to deploy.rb

namespace :mod_rails do
  desc <<-DESC
  Restart the application altering tmp/restart.txt for mod_rails.
  DESC
  task :restart, :roles => :app do
    run "touch  #{release_path}/tmp/restart.txt"
  end
end

namespace :deploy do
  %w(start restart).each { |name| task name, :roles => :app do mod_rails.restart end }
end

Perform a Rails find() and iterate over the resulting records in groups

module ActiveRecord
  class Base
    # This method lets you iterate over the results of a .find, in groups.
    # (Basically an interface to LIMIT.)
    # Anything you can pass as options to .find, you can pass here. 
    # Example 1:
    #   Order.each_by(100, :conditions => { :cc_processed_at => nil }) do |order|
    #     # do stuff with order
    #   end
    # Example 2:
    #   Person.each_by(50, :order => 'name') do |person, index|
    #     # do stuff with person and index
    #   end
    # Pass :update => true in the options to print a message before each group is
    # fetched from the db.
    #
    # Author: Elliot Winkler <elliot.winkler@gmail.com>
    # Source: http://snippets.dzone.com/posts/show/5461
    def self.each_by(group_size, options={}, &blk)
      update = options.delete(:update) || false
      num_records = count(options.except(:from))
      return 0 if num_records == 0
      #raise "Number of records: #{num_records}"
      also_pass_offset = (blk.arity == 2)
      0.step(num_records, group_size) do |offset|
        find_options = { :offset => offset, :limit => group_size }.merge(options)
        if update
          if num_records == 1
            puts ">> Reading the only record."
          else
            start_offset = offset + 1
            end_offset   = offset + group_size
            end_offset   = num_records if num_records < end_offset
            puts ">> Reading records #{start_offset}-#{end_offset}."
          end
        end 
        find(:all, find_options).each do |record|
          also_pass_offset ? blk.call(record, offset) : blk.call(record)
        end
      end
      num_records
    end
  end
end

annotate models with associations

slightly modified http://repo.pragprog.com/svn/Public/plugins/annotate_models/lib/annotate_models.rb to include short declarations for model associations.

require "config/environment"

MODEL_DIR   = File.join(RAILS_ROOT, "app/models")
FIXTURE_DIR = File.join(RAILS_ROOT, "test/fixtures")

module AnnotateModels

  PREFIX = "== Schema Information"
  
  # Simple quoting for the default column value
  def self.quote(value)
    case value
      when NilClass                 then "NULL"
      when TrueClass                then "TRUE"
      when FalseClass               then "FALSE"
      when Float, Fixnum, Bignum    then value.to_s
      # BigDecimals need to be output in a non-normalized form and quoted.
      when BigDecimal               then value.to_s('F')
      else
        value.inspect
    end
  end

  # Use the column information in an ActiveRecord class
  # to create a comment block containing a line for
  # each column. The line contains the column name,
  # the type (and length), and any optional attributes
  def self.get_schema_info(klass, header)
    info = "# == Model #{klass}\n# #{header}\n#\n"
    info << "# Table name: #{klass.table_name}\n#\n"
    
    max_size = klass.column_names.collect{|name| name.size}.max + 1
    klass.columns.each do |col|
      attrs = []
      attrs << "default(#{quote(col.default)})" if col.default
      attrs << "not null" unless col.null
      attrs << "primary key" if col.name == klass.primary_key

      col_type = col.type.to_s
      if col_type == "decimal"
        col_type << "(#{col.precision}, #{col.scale})"
      else
        col_type << "(#{col.limit})" if col.limit
      end 
      info << sprintf("#  %-#{max_size}.#{max_size}s:%-15.15s %s\n", col.name, col_type, attrs.join(", "))
    end
    assoc_list = klass.reflect_on_all_associations.sort {|x,y| d = x.class_name.to_s <=> y.class_name.to_s; c = d == 0 ? x.macro.to_s <=> y.macro.to_s : d; c == 0 ? x.name.to_s <=> y.name.to_s : c }
    unless assoc_list.empty?
      info << "#\n# == Associations\n" 
      assoc_list.each do |assoc|
        ao = assoc.options.dup
        ao.delete(:class_name)
        line = "# * " +sprintf("<tt>%-25s :%-25s (%s) %s</tt>", assoc.macro, assoc.name, assoc.class_name, ao.empty? ? '' : ao.inspect)
        info << line << "\n"
      end 
    end
    info << "#\n\n"
  end

  # Add a schema block to a file. If the file already contains
  # a schema info block (a comment starting
  # with "Schema as of ..."), remove it first.

  def self.annotate_one_file(file_name, info_block)
    if File.exist?(file_name)
      content = File.read(file_name)

      # Remove old schema info
      content.sub!(/^# #{PREFIX}.*?\n(#.*\n)*\n/, '')

      # Write it back
      File.open(file_name, "w") { |f| f.puts info_block + content }
    end
  end
  
  # Given the name of an ActiveRecord class, create a schema
  # info block (basically a comment containing information
  # on the columns and their types) and put it at the front
  # of the model and fixture source files.

  def self.annotate(klass, header)
    info = get_schema_info(klass, header)
    
    model_file_name = File.join(MODEL_DIR, klass.name.underscore + ".rb")
    annotate_one_file(model_file_name, info)

    fixture_file_name = File.join(FIXTURE_DIR, klass.table_name + ".yml")
    annotate_one_file(fixture_file_name, info)
  end

  # Return a list of the model files to annotate. If we have 
  # command line arguments, they're assumed to be either
  # the underscore or CamelCase versions of model names.
  # Otherwise we take all the model files in the 
  # app/models directory.
  def self.get_model_names
    models = ARGV.dup
    models.shift
    
    if models.empty?
      Dir.chdir(MODEL_DIR) do 
        models = Dir["**/*.rb"]
      end
    end
    models
  end

  # We're passed a name of things that might be 
  # ActiveRecord models. If we can find the class, and
  # if its a subclass of ActiveRecord::Base,
  # then pas it to the associated block

  def self.do_annotations
    header = PREFIX.dup
    version = ActiveRecord::Migrator.current_version rescue 0
    if version > 0
      header << "\n# Schema version: #{version}"
    end
    
    self.get_model_names.each do |m|
      class_name = m.sub(/\.rb$/,'').camelize
      begin
        klass = class_name.split('::').inject(Object){ |klass,part| klass.const_get(part) }
        if klass < ActiveRecord::Base && !klass.abstract_class?
          puts "Annotating #{class_name}"
          self.annotate(klass, header)
        else
          puts "Skipping #{class_name}"
        end
      rescue Exception => e
        puts "Unable to annotate #{class_name}: #{e.message}"
      end
      
    end
  end
end

Testing for nil or empty params in Ruby on Rails

I find myself doing these 4 things a lot:
if params[:object] && !params[:object].empty
if params[:object] && params[:object] == value
if params[:object][:attribute] && !params[:object][:attribute].empty
if params[:object][:attribute] && params[:object][:attribute] == value

I put params_check() in my application.rb and it allows me to do this instead:
if params_check(:object)
if params_check(:object, value)
if params_check([:object, :attribute])
if params_check([:object, :attribute], value)

  def params_check(*args)
    if args.length == 1
      if args[0].class == Array
        if params[args[0][0]][args[0][1]] && !params[args[0][0]][args[0][1]].empty?
          true
        end
      else        
        if params[args[0]] && !params[args[0]].empty?
          true
        end
      end
    elsif args.length == 2
      if args[0].class == Array
        if params[args[0][0]][args[0][1]] && params[args[0][0]][args[0][1]] == args[1]
          true
        end
      else
        if params[args[0]] && params[args[0]] == args[1]
          true
        end
      end  
    end
  end

I stole this off another snippet and modified it to add more conditions. Thanks to whoever it was.

Rails helpers for A List Apart No. 256

I cooked up some Ruby on Rails helpers for testing the techniques in the article Accessible Data Visualization with Web Standards from A List Apart No. 256. If you want to know more about Rails, check out No. 257. If you want to be smarter, read A List Apart every week.

def chartlist(data)
  total = data.inject(0.0) { |sum, datum| sum + datum[:count] }
  bars = ''

  data.each do |datum|
    link  = content_tag 'a', datum[:name], :href => datum[:href]
    count = content_tag 'span', datum[:count], :class => 'count'
    index = content_tag 'span', "(#{(datum[:count]/total*100).to_i}%)", :class => 'index', :style => "width: #{(datum[:count]/total*100).to_i}%"
    bars << content_tag('li', link << count << index)
  end

  content_tag 'ul', bars, :class => 'chartlist'
end


Sample data for a chartlist (example)

data = [{ :name => 'Apples',   :count => 420, :href => 'http://www.example.com/fruits/apples/' },
        { :name => 'Bananas',  :count => 280, :href => 'http://www.example.com/fruits/bananas/' },
        { :name => 'Cherries', :count => 200, :href => 'http://www.example.com/fruits/cherries/' },
        { :name => 'Dates',    :count => 100, :href => 'http://www.example.com/fruits/dates/' }]


def sparkline(data)
  max = data.sort.last.to_f
  sparklines = ''

  data.each_with_index do |datum, index|
    count_string = datum.to_s
    '(' << count_string if index == 0
    count_string << ',' if index != data.length
    count_string << ')' if index == data.length
    count = content_tag 'span', count_string, :class => 'count', :style => "height: #{(datum/max*100).to_i}%"
    index = content_tag 'span', count << ' ', :class => 'index'
    sparklines << index
  end

  content_tag('span', sparklines, :class => 'sparkline')
end


Sample data for sparklines (example)

data = [60, 220, 140, 80, 110, 90, 180, 140, 120, 160, 175, 225, 175, 125]


def timeline(data)
  max = data.sort { |a, b| a[:count] <=> b[:count] }.last[:count]
  bars = ''

  data.each do |datum|
    label = content_tag 'span', datum[:label], :class => 'label'
    count = content_tag 'span', "(#{datum[:count]})", :class => 'count', :style => "height: #{(datum[:count]/max.to_f*100).to_i}%"
    link  = content_tag 'a', label << count, :href => datum[:href], :title => "#{datum[:label]}: #{datum[:count]}"
    bars << content_tag('li', link, :style => "width: #{(100.0/data.length).to_i}%")
  end

  content_tag 'ul', bars, :class => 'timeline'
end


Sample data for a timeline (example)

data = [{ :date => '2007-12-01', :count =>  40, label => '1' },
        { :date => '2007-12-02', :count => 100, label => '2' },
        { :date => '2007-12-03', :count => 150, label => '3' }]

rails sendmail settings

config.action_mailer.raise_delivery_errors = true
ActionMailer::Base.delivery_method = :sendmail
ActionMailer::Base.sendmail_settings = {
    :location       => '/usr/sbin/sendmail',
    :arguments      => '-i -t'
}

record grouping

@users = User.find(
  :all, 
  :select => "MONTH(created_at) as month, YEAR(created_at) as year, COUNT(*) AS records",
  :conditions => ["admin = 0'"], 
  :group => "year, month")

<% for @user in @users %>
  <%=@user.month%>
  <%=@user.year%>
  <%=@user.records%>
<% end %>

date_select conversion

function to convert a value from a date_select into a more sql-friendly value

<%=date_select(:date,'',:start_year => 1950,:include_blank => false, :default => { :year => '1970' })%>

def convert_date(obj) 
  return “#{obj[‘(1i)’]}-#{obj[‘(2i)’]}-#{obj[‘(3i)’]}” 
end

ISO 8601 date format for microformats

Used this in Ruby to get the ISO 8601 (see RFC 3339) full date format for an hEvent Microformat. Doubtless usable in other situations.

strftime('%Y-%m-%dT%H:%M:%S%z')


How to use:

<abbr class="dtstart" title="<%= event.start_date.strftime('%Y-%m-%dT%H:%M:%S%z') %>"><%= event.start_date.to_s(:long) %></abbr>
« Newer Snippets
Older Snippets »
Showing 1-10 of 443 total  RSS