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

About this user

Todd Sayre http://del.icio.us/sporkyy

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

Rails ajax star rater

Here's some Rails code I created to try out the CSS Star Rating Redux from Komodo Media.

I set up my routes.rb to use REST.

   1  map.resources :titles, :member => { :rate => :any }


I use the Ruby Linguistics Framework to make this implementation easier. Install it using RubyGems (sudo gem install linguistics). And then put the following code at the top of your application_helper.rb file.

   1  require 'linguistics'
   2  Linguistics::use(:en)  # extends Array, String, and Numeric


This code goes in the page you want the rater to appear in, in this example, show.html.erb.

   1  <ul class="star-rating" id="<%= dom_id(@title) -%>_rating"><%= render :partial => '/partials/star_rating', :locals => { :record => @title } %></ul>


Create a partial called _star_rating.html.erb in your RAILS_ROOT/views/partials directory.

   1  <li class="current-rating" style="width: <%= number_to_percentage((record.rating.to_f * 25) / (5 * 25) * 100) -%>;">Currently <%= record.rating -%>/5 Stars.</li>
   2  <% (1..5).each do |i| -%>
   3      <li><%= link_to_remote pluralize(i, 'Star'), {
   4          :update => "#{dom_id(record)}_rating",
   5          :url => eval("rate_#{record.class.name.downcase}_url(:rating => #{i})")
   6      }, {
   7          :class => "#{i.en.numwords}-#{i.abs == 1 ? 'star' : 'stars'}",
   8          :title => "#{pluralize(i, 'star')} out of 5"
   9      } -%></li>
  10  <% end -%>

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.

   1  def chartlist(data)
   2    total = data.inject(0.0) { |sum, datum| sum + datum[:count] }
   3    bars = ''
   4  
   5    data.each do |datum|
   6      link  = content_tag 'a', datum[:name], :href => datum[:href]
   7      count = content_tag 'span', datum[:count], :class => 'count'
   8      index = content_tag 'span', "(#{(datum[:count]/total*100).to_i}%)", :class => 'index', :style => "width: #{(datum[:count]/total*100).to_i}%"
   9      bars << content_tag('li', link << count << index)
  10    end
  11  
  12    content_tag 'ul', bars, :class => 'chartlist'
  13  end


Sample data for a chartlist (example)

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


   1  def sparkline(data)
   2    max = data.sort.last.to_f
   3    sparklines = ''
   4  
   5    data.each_with_index do |datum, index|
   6      count_string = datum.to_s
   7      '(' << count_string if index == 0
   8      count_string << ',' if index != data.length
   9      count_string << ')' if index == data.length
  10      count = content_tag 'span', count_string, :class => 'count', :style => "height: #{(datum/max*100).to_i}%"
  11      index = content_tag 'span', count << ' ', :class => 'index'
  12      sparklines << index
  13    end
  14  
  15    content_tag('span', sparklines, :class => 'sparkline')
  16  end


Sample data for sparklines (example)

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


   1  def timeline(data)
   2    max = data.sort { |a, b| a[:count] <=> b[:count] }.last[:count]
   3    bars = ''
   4  
   5    data.each do |datum|
   6      label = content_tag 'span', datum[:label], :class => 'label'
   7      count = content_tag 'span', "(#{datum[:count]})", :class => 'count', :style => "height: #{(datum[:count]/max.to_f*100).to_i}%"
   8      link  = content_tag 'a', label << count, :href => datum[:href], :title => "#{datum[:label]}: #{datum[:count]}"
   9      bars << content_tag('li', link, :style => "width: #{(100.0/data.length).to_i}%")
  10    end
  11  
  12    content_tag 'ul', bars, :class => 'timeline'
  13  end


Sample data for a timeline (example)

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

Javascript Rails-like inflector

I was using Ajax to do some DOM manipulation in a Rails app I was working on. None of what I was doing needed to involve a round trip to server, the only reason I hit the server at all was to take advantage of Rails' (well, ActiveSupport's) pluralize function. Also, this technique required an extra action that I decided to eliminate as I try to move to a more RESTful architecture.

The only part of ActiveSupport's Inflector class I implemented are the ones I needed. I implemented even fewer of Rails' Inflector-based functions.

Stick all this in a file, such as "inflector.js".
   1  /*
   2   * This script depends on no outside libraries.
   3   */
   4  
   5  Inflector = {
   6      /*
   7       * The order of all these lists has been reversed from the way 
   8       * ActiveSupport had them to keep the correct priority.
   9       */
  10      Inflections: {
  11          plural: [
  12              [/(quiz)$/i,               "$1zes"  ],
  13              [/^(ox)$/i,                "$1en"   ],
  14              [/([m|l])ouse$/i,          "$1ice"  ],
  15              [/(matr|vert|ind)ix|ex$/i, "$1ices" ],
  16              [/(x|ch|ss|sh)$/i,         "$1es"   ],
  17              [/([^aeiouy]|qu)y$/i,      "$1ies"  ],
  18              [/(hive)$/i,               "$1s"    ],
  19              [/(?:([^f])fe|([lr])f)$/i, "$1$2ves"],
  20              [/sis$/i,                  "ses"    ],
  21              [/([ti])um$/i,             "$1a"    ],
  22              [/(buffal|tomat)o$/i,      "$1oes"  ],
  23              [/(bu)s$/i,                "$1ses"  ],
  24              [/(alias|status)$/i,       "$1es"   ],
  25              [/(octop|vir)us$/i,        "$1i"    ],
  26              [/(ax|test)is$/i,          "$1es"   ],
  27              [/s$/i,                    "s"      ],
  28              [/$/,                      "s"      ]
  29          ],
  30          singular: [
  31              [/(quiz)zes$/i,                                                    "$1"     ],
  32              [/(matr)ices$/i,                                                   "$1ix"   ],
  33              [/(vert|ind)ices$/i,                                               "$1ex"   ],
  34              [/^(ox)en/i,                                                       "$1"     ],
  35              [/(alias|status)es$/i,                                             "$1"     ],
  36              [/(octop|vir)i$/i,                                                 "$1us"   ],
  37              [/(cris|ax|test)es$/i,                                             "$1is"   ],
  38              [/(shoe)s$/i,                                                      "$1"     ],
  39              [/(o)es$/i,                                                        "$1"     ],
  40              [/(bus)es$/i,                                                      "$1"     ],
  41              [/([m|l])ice$/i,                                                   "$1ouse" ],
  42              [/(x|ch|ss|sh)es$/i,                                               "$1"     ],
  43              [/(m)ovies$/i,                                                     "$1ovie" ],
  44              [/(s)eries$/i,                                                     "$1eries"],
  45              [/([^aeiouy]|qu)ies$/i,                                            "$1y"    ],
  46              [/([lr])ves$/i,                                                    "$1f"    ],
  47              [/(tive)s$/i,                                                      "$1"     ],
  48              [/(hive)s$/i,                                                      "$1"     ],
  49              [/([^f])ves$/i,                                                    "$1fe"   ],
  50              [/(^analy)ses$/i,                                                  "$1sis"  ],
  51              [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, "$1$2sis"],
  52              [/([ti])a$/i,                                                      "$1um"   ],
  53              [/(n)ews$/i,                                                       "$1ews"  ],
  54              [/s$/i,                                                            ""       ]
  55          ],
  56          irregular: [
  57              ['move',   'moves'   ],
  58              ['sex',    'sexes'   ],
  59              ['child',  'children'],
  60              ['man',    'men'     ],
  61              ['person', 'people'  ]
  62          ],
  63          uncountable: [
  64              "sheep",
  65              "fish",
  66              "series",
  67              "species",
  68              "money",
  69              "rice",
  70              "information",
  71              "equipment"
  72          ]
  73      },
  74      ordinalize: function(number) {
  75          if (11 <= parseInt(number) % 100 && parseInt(number) % 100 <= 13) {
  76              return number + "th";
  77          } else {
  78              switch (parseInt(number) % 10) {
  79                  case  1: return number + "st";
  80                  case  2: return number + "nd";
  81                  case  3: return number + "rd";
  82                  default: return number + "th";
  83              }
  84          }
  85      },
  86      pluralize: function(word) {
  87          for (var i = 0; i < Inflector.Inflections.uncountable.length; i++) {
  88              var uncountable = Inflector.Inflections.uncountable[i];
  89              if (word.toLowerCase == uncountable) {
  90                  return uncountable;
  91              }
  92          }
  93          for (var i = 0; i < Inflector.Inflections.irregular.length; i++) {
  94              var singular = Inflector.Inflections.irregular[i][0];
  95              var plural   = Inflector.Inflections.irregular[i][1];
  96              if ((word.toLowerCase == singular) || (word == plural)) {
  97                  return plural;
  98              }
  99          }
 100          for (var i = 0; i < Inflector.Inflections.plural.length; i++) {
 101              var regex          = Inflector.Inflections.plural[i][0];
 102              var replace_string = Inflector.Inflections.plural[i][1];
 103              if (regex.test(word)) {
 104                  return word.replace(regex, replace_string);
 105              }
 106          }
 107      }
 108  }
 109  
 110  function ordinalize(number) {
 111      return Inflector.ordinalize(number);
 112  }
 113  
 114  /*
 115   * Javascript doesn't have optional parameters or overloading so I had to use
 116   * the ever popular pseudo options hash object technique.
 117   * required properties:
 118   *     count    Number of objects to pluralize
 119   *     singular Singular noun for the objects
 120   * optional property:
 121   *     plural   Plural (probably irregular) noun for the objects
 122   * examples:
 123   *      pluralize({ count: total_count, singular: "Issue" })
 124   *      pluralize({ count: total_count, singular: "Goose", plural: "Geese" })
 125   */
 126  function pluralize(options) {
 127      return options.count + " " + (1 == parseInt(options.count) ?
 128          options.singular :
 129          options.plural || Inflector.pluralize(options.singular));
 130  }

Number to Currency with Cents

A slight alteration to the default Rails currency formatting helper to show numbers in cents if the number is less than $1.00. For example $0.99 would instead become 99&cent;.

   1  
   2  def number_to_currency_with_cents(number, options = {})
   3      options = options.stringify_keys
   4      precision = options.delete('precision') { 2 }
   5      unit = options.delete('unit') { '$' }
   6      fractional_unit = options.delete('fractional_unit') { '&cent;' }
   7      separator = options.delete('separator') { '.' }
   8      delimiter = options.delete('delimiter') { ',' }
   9      separator = '' unless precision > 0
  10      begin
  11          fraction = number.abs % 1.0
  12          body = number.floor
  13          if body != 0 || body == 0 && fraction == 0 then
  14              parts = number_with_precision(number, precision).split('.')
  15              unit + number_with_delimiter(parts[0], delimiter) + separator + parts[1].to_s
  16          else
  17              (fraction * 100).to_i.to_s + fractional_unit
  18          end
  19      rescue
  20          number
  21      end
  22  end


I'm really tempted to go through and replace that whole thing with my own code, but it works, so I'm happy.

PrototypeHelper :with helper

This method is for use in conjuction with the Ruby on Rails Module ActionView::Helpers::PrototypeHelper.

The options hash takes any number of key/value pairs the key becomes the name of the parameter passed in the with value and the value becomes a javascript expression

key — name of the parameter
value — a fragment of javascript that will be the value of the parameter

Example
>> params_for_with(:clean_range => 'clean_range', :raw_range => 'raw_range', :total_count => 'total_count')
=> 'total_count=' + total_count + '&' + 'clean_range=' + clean_range + '&' + 'raw_range=' + raw_range


Don‘t forget you won’t necessarily get the parameters out in the same order you put them in, such is the nature of hashes

   1  
   2  def params_for_with(options = {})
   3      options.collect { |param_name, js_fragment| "'#{param_name}='+#{js_fragment}" }.join("+'&'+")
   4      # or this one
   5      #options.stringify_keys.collect { |param_name, js_fragment| '"' << param_name << '="+' << js_fragment }.join('+"&"+')
   6  end
« Newer Snippets
Older Snippets »
Showing 1-5 of 5 total  RSS