Articles tagged with ruby
Often, when it comes to views I have to group records and present it to the user grouped by some condition. For example, I would like to list all news articles grouped by year.
To accomplish this, I find it easiest that records are grouped in a hash, key should be year when article is published and value would be array of objects matching published on these year.
Before, I used custom function that would walk throught all elements of array calling custom block for each member and creating new hash with result value of the block as key and array of elements as value.
Today I discover classify method in Set class that would do just what I need (thanks to Ruby Cookbook for that).
So, the code to group all news articles by year published is:
@groups = NewsArticle.find(:all).to_set.classify {
|article| article.published_on.year}
and view would be something like these:
<%@groups.each do |year, articles|%>
<h1><%=year%></h1>
<%=articles.collect {|a| \"<p>a.name</p>\"}.join%>
<%end%>
Short and sweet. Same method can be used to group anything, names by first letter, products by price range, etc.
Sooner or later need to override some built in Rails helpers would occur. For example, I like to use number_to_currency helper to format prices in my application, but I want all prices to be formated in euros instead of dollars.
Worth noting is that you cannot simple redefine number_to_currency in application_helper.rb what would be the first thing on my mind to do. You can not redefine original helper method in ActionView::Base class as well. That is because helpers are included as mixin and methods from module are made available to class that includes the module, they are not copied, so if module methods are changed later so are the modules method in a class.
Original helper method should be replaced in module where it comes from and in case of currencies this is ActionView::Helpers::NumberHelper.
Here is example that replaces original number_to_currency method and set default currency to Euro:
module ActionView
module Helpers
module NumberHelper
def number_to_currency_with_euro(number, options = {})
defaults = {:unit => ''}
s = number_to_currency_without_euro(number, defaults.merge(options))
s << ' €' unless options[:unit]
end
alias_method_chain :number_to_currency, :euro
end
end
end
Ruby has three classes for working with date and time: Date, DateTime which subclasses Date and Time. There is an interesting article why we need all 3 classes, and here are some notes about working with dates:
Time.now != DateTime.now && Time.superclass != Date
- There is no method in
Time class to convert object to a Date object, but you can write date = Date.new(time.year, time.mon, time.day). Rails extends DateTime and Time classes which allows to_date and to_time conversions for both classes.
- Today is
Date.today and now it is Time.now, there is no such thing as Date.now but there is Time.today (even I didn’t saw it in RDocs)
- Tomorrow is
Date.today+1, yestrday Date.today-1, to add or substract a month use Date.today >> 1 or Date.today << 1. See also Rails extensions to time class which allows to write things like Date.today.to_time.at_beginning_of_week
- Date class includes Comparable module which allows us to write
some_date.between?(Date.today, Date.today + 7)
Time.now.beginning_of_month.to_date.upto( Time.now.next_month.beginning_of_month.to_date-1) {|d| puts d.to_s} would print all days in current month in your Rails application.
Standard Ruby library also includes ParseDate library for parsing dates and returning array of values. Rails use ParseDate.parsedate to create dates so if you need to support input of additional date formats consider extending parsedate. I am not sure why Date.parse does not use ParseDate.parse but have its own implementation.
I started to use Ruby FPDF to create PDF documents from our new Rails application MojGost.com. Ruby FPFD like it’s PHP counterpart does not have methods for creating tables. However, there are many examples and scripts available and that allowed me to quickly write small Ruby module which adds few methods for easy table creation.
Fpdf::Table main features:
- word wraping text in cells, based on width of columns
- page breaks on rows if table is too long
Download Fpdf::Table or see some examples below.
Example 1. simple table
require 'FPDF'
require 'fpdf/table'
class FPDF
include Fpdf::Table
end
pdf = FPDF.new
pdf.AddPage
pdf.SetFont('helvetica','',10)
data = [
['100', 'lorem ipsum dorem'],
['100', 'lorem ipsum dorem'],
['100', 'lorem ipsum dorem'],
]
pdf.table(data)
pdf.Output('test_fpdf_table_1.pdf')
View Example 1 PDF
Example 2. width, word-wrap, aligment, page break
require 'FPDF'
require 'fpdf/table'
class FPDF
include Fpdf::Table
end
pdf = FPDF.new
pdf.AddPage
pdf.SetFont('helvetica','',10)
data = []
30.times { |i| data << [i.to_s, '-', 'Lorem ipsum dolor sit' * 10] }
columns = [
{:title => '#1', :aligment => 'R', :width => 20},
{:title => '#2', :width => 20},
{:title => 'Text'}
]
pdf.table(data, columns)
pdf.Output('test_fpdf_table_2.pdf')
View Example 2 PDF
Class methods in Ruby are methods that work without being tied to any particular object (Java and PHP5 have static methods for similiar purpose). Class methods are distinguished from instance methods by placing the class name and a period in front of the method name. One thing that may not be obvious if you want to inherit class method is how to call equally named class method from parent class.
If you try to use super.class_method_name it would not work. That’s because class_method_name is class method and not instance method and as such it does not exists in object. Fortunately, classes in Ruby are objects too and you can interact with class like you interact with any other objects.
Enough talking, here is example:
class User
def User.columns
"name,email"
end
end
class Customer < User
def Customer.columns
self.superclass.columns + ",saldo"
end
end
puts Customer.columns # << name,email,saldo
Both PHP functions provides information about a variable passed as argument. It is often used in development to get quick and human-readable info about array or object. If you are using Rails you can use DebugHelper’s debug(object) helper function. Note that helpers are available only in views. In controllers, models and other Ruby code you can use ‘puts YAML::dump(object)’ method to get readable info about object.