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-9 of 9 total  RSS 

Custom validation with rails: words with more than 26 characters

This goes in whatever model you're validating. "Subject" can be any of the symbols in your model and doesn't need the : in front of it.
def validate
	if subject.split.any?{|w| w.length > 26}
		errors.add(:subject, "cannot have words more than 26 consecutive characters")
	end
end

Rails auto select text field

A simple helper to create those snazzy on-click-auto-select text fields you see on all the video-sharing sites.

def auto_select_text_field_tag(name, value = nil, options = {})
  text_field_tag(name,
                 value,
                 { :onclick => "$(’#{name}’).select()",
                   :readonly => "true" }.merge(options))
end



A _little_ more info on my blog.

~Barry Hess

Produce GIF or PNG barcode images from a Ruby on Rails application using RMagick and Gbarcode

This is a Ruby on Rails controller that produces PNG barcode images using RMagick (http://rmagick.rubyforge.org/) and Gbarcode (http://gbarcode.rubyforge.org/), the Ruby Gnu Barcode ( http://www.gnu.org/software/barcode/barcode.html ) wrapper. You will need to install RMagick and Gbarcode.

On Mac OS X, you can use the Locomotive RMagick bundle (http://locomotive.raaum.org/bundles/index.html) if you install the gbarcode gem into it first, for instance:

% export GEM_HOME=/Applications/Locomotive2/Bundles/rmagickRailsMar2007_i386.locobundle/framework/lib/ruby/gems/1.8/
% gem install gbarcode


To use it, save this code as barcode_controller.rb in the apps/controllers directory of your Rails application. Generate the barcodes using a URL like this:

http://localhost:3000/barcode/get_barcode_image?string=foo

This example uses the BARCODE_128 encoding; you can use different barcode encodings by adjusting the code. To produce PNG images, make sure you have have the PNG libraries installed on your system, and that your ImageMagick is compiled with PNG support, and then change 'image/gif' to 'image/png' and im.format = "GIF" to im.format = "PNG".

# $RAILS_ROOT/apps/controllers/barcode_controller.rb
class BarcodeController < ApplicationController

  def get_barcode_image
     string_to_encode = params[:string]
     barcode_image = BarcodeGenerator.get_barcode_image(string_to_encode)
     send_data(barcode_image, :type     => 'image/gif',
                                  :disposition => 'inline')
  end
end


# $RAILS_ROOT/app/helpers/barcode_generator.rb
#
# note: this will not work without rmagick (Ruby ImageMagick interface) and gbarcode (GNU barcode) 
# gems installed. rmagick needs ImageMagick plus dependencies.

class BarcodeGenerator

  # Uses subprocesses because 
  # 1. ImageMagick/RMagick leaks memory,
  #    and doesn't work in a long-running process. The fork makes it safe.
  # 2. The output from the Gbarcode and ImageMagick is often longer than the pipe buffer,
  #    so we have to empty the buffer from another subprocess
  def BarcodeGenerator.get_barcode_image(barcode_string)
    return BarcodeGenerator.get_subprocess_output do
                   barcode_generator = BarcodeGenerator.new
                   $stdout.write(barcode_generator.get_barcode_image(barcode_string))
    end
  end

  def initialize
    # we do the imports here to protect long-running processes (like mongrel) from ImageMagick's memory leaks
    require 'RMagick'
    require 'gbarcode'
  end

  def get_barcode_image(string_to_encode)
    if string_to_encode.nil?
      string_to_encode = "No string specified"
    end
    string_to_encode = remove_rails_file_extension(string_to_encode)
    eps_barcode = get_barcode_eps(string_to_encode)
    gif_barcode = convert_eps_to_gif(eps_barcode)
    return gif_barcode
  end

  def remove_rails_file_extension(string_to_encode)
    if string_to_encode[-4..-1] == ".png"
      string_to_encode = string_to_encode[0..-5]
    end
    return string_to_encode
  end

  def get_barcode_eps(string_to_encode)
    barcode_object = Gbarcode.barcode_create(string_to_encode)
    Gbarcode.barcode_encode(barcode_object, Gbarcode::BARCODE_128)
    return BarcodeGenerator.get_subprocess_output do
        Gbarcode.barcode_print(barcode_object, $stdout, Gbarcode::BARCODE_OUT_EPS)    
    end
  end
  
  def convert_eps_to_gif(eps_image)
    base64_eps_image = Base64.encode64(eps_image)
    im = Magick::Image::read_inline(base64_eps_image).first
    im.format = "GIF"
    return BarcodeGenerator.get_subprocess_output do
       im.write($stdout) 
    end
  end

  # execute a block's code in a subprocess, returning any output
  def BarcodeGenerator.get_subprocess_output()
    data = ""
    IO.popen('-', 'r+') do |child_filehandle|
      if child_filehandle
        begin
          data = child_filehandle.read
        ensure
          child_filehandle.close_write
        end
      else
        yield
      end
    end
    return data
  end

end    

create an array or split a long string seperated by tabs newlines carriage returns and commas.

create an array or split a long string seperated by tabs newlines carriage returns and commas.

EG

emails = "skdjf@sdklfj.com sdflj@kj.com sldfj@klj.com, slkj@kjl.com,lskjdf@lkj.com, \r\nlkjkjl@kjk.com"

becomes

=> ["skdjf@sdklfj.com", "sdflj@kj.com", "sldfj@klj.com", "slkj@kjl.comlskjdf@lkj.com", "lkjkjl@kjk.com"]

emails = emails.split(/,/).join().split()

ActiveRecord: cache column information

// Cache the column information so that no more query will be
// sent to the server thereafter

class ActiveRecord::Base
	
	@@_cached_columns = {}
	class << self
		
		alias :old_columns :columns
		
		def columns
			return @@_cached_columns[table_name] if @@_cached_columns[table_name]
			@@_cached_columns[table_name] = old_columns
		end
		
	end
	
end

Helper for quicly creating standard tables

I often want to display an array of objects as a table on a page, and I end up doing the the same things over and over again. I wrote this helper method to speed things up:

def table(collection, headers, options = {}, &proc)
  options.reverse_merge!({
    :placeholder  => 'Nothing to display',
    :caption      => nil,
    :summary      => nil,
    :footer       => ''
  })
  placeholder_unless collection.any?, options[:placeholder] do
    summary = options[:summary] || "A list of #{collection.first.class.to_s.pluralize}"
    output = "<table summary=\"#{summary}\">\n"
    output << content_tag('caption', options[:caption]) if options[:caption]
    output << "\t<caption>#{options[:caption]}</caption>\n" if options[:caption]
    output << content_tag('thead', content_tag('tr', headers.collect { |h| "\n\t" + content_tag('th', h) }))
    output << "<tfoot><tr>" + content_tag('th', options[:footer], :colspan => headers.size) + "</tr></tfoot>\n" if options[:footer]
    output << "<tbody>\n"
    concat(output, proc.binding)
    collection.each do |row|
      proc.call(row, cycle('odd', 'even'))
    end
    concat("</tbody>\n</table>\n", proc.binding)
  end
end


Writing...

<% table(@posts, %w{ID title}) do |post, klass| -%>
    <tr class="<%= klass %>">
      <td><%= post.id</td>
      <td><%= post.title </td>
    </tr>
<% end -%>


results in...

<table summary="A list of posts">
  <thead>
    <tr>
      <th>ID</th>
      <th>Title</th>
    </tr>
  </thead>
  <tfoot><tr><td colspan="2"></td></tr></tfoot>
  <tbody>
    <tr>
      <td>1</td>
      <td>My first post</td>
    </tr>
  </tbody>
</table>


Or, when the collection is an empty array (collection.any? returns false), a placeholder message is displayed:

<p class="placeholder">Nothing to display</p>


So you pass in your collection and an array of strings as your table headers as the first two arguments, and the third is a hash of options you can use to set the contents of the table's summary-attribute, the caption and footer-elements and the placeholder.

The summary attribute defaults to "A list of [objects]", where 'objects' is derived from the class name of the collection.

The function finally takes a block for every element in the collection, yeilding it the element and either 'odd' or 'even' so you can use CSS-classes to apply a zebra stripes effect.

Helpers for placeholder messages

When there are no results to display for a user you often want to tell so using a placeholder message, such as 'Sorry, no posts matched your criteria' or 'You have no recent purchases'.

I created these two helpers to make using placeholder a little bit easier.

def placeholder(message = 'Nothing to display', options = {}, &proc)
  # set default options
  o = { :class => 'placeholder', :tag => 'p' }.merge(options)

  # wrap the results of the supplied block, or
  # just print out the message
  if proc
    t = o.delete(:tag)
    concat tag(t, o, true), proc.binding
    yield
    concat "</#{t}>", proc.binding
  else
    content_tag o.delete(:tag), message, o
  end
end
  
def placeholder_unless(condition, *args, &proc)
  condition ? proc.call : concat(placeholder(args), proc.binding)
end


Now you can use it as follows:

<%= placeholder :message => 'Nothing found' %>

<% placeholder do %>
Nothing found.
<% end %>


Results in:

<p class="placeholder">Nothing found</p>


The second function allows the following usage:

<% placeholder_unless @posts.any?, 'No posts found' do %>
  <%= render :partial => @post %>
<% end %>


The point is it all results in a nice, painless message with consistent markup and styling and I find it makes my code a bit more readable.

I'm sure the code could be optimized but for now it works.

Don't display the delete link unless no service events exist

// This is the link I'll use when I get to adding the delete methods in the controllers.

<% if @client.service_events.empty? -%> | <%= link_to "delete", :controller => "admin", :action => "destroy_client", :id => @client %><% end -%>

Highlight link for current action

It's very common to want to highlight the current link within a navigation list for the current action being performed.

What follows is an extremely simplistic approach to solving this, so build upon it as you wish.


The first thing to do is add the following code to your application_helper.rb file
def section_link(name,options)
    if options[:action] == @current_action and options[:controller] == @current_controller
       link_to(name, options, :class => 'on')
    else
      link_to(name,options)
    end
end


The above method always expects an :action key to be passed in with the options hash, so if you're one of those people who just pass in the :controller and not the :action so as to default to whatever method you've set it in your routes.rb file, then this won't work for you.

Finally put this in you're application.rb file, as it makes the current executing action and controller name available to the helper.
before_filter :instantiate_controller_and_action_names

def instantiate_controller_and_action_names
      @current_action = action_name
      @current_controller = controller_name
end 



In your view use
<%=section_link('Home',:controller => 'articles', :action => 'index')%>


Make sure you have a CSS class called "on" or edit the above code. The following CSS is just an example.

a.on{
  border-bottom: solid 2px #000;
}

« Newer Snippets
Older Snippets »
Showing 1-9 of 9 total  RSS