Cache Single ActiveRecord Objects with model_cached!
January 6th, 2010 by ary
I’ve just released a very simple Rails plugin that gives you the ability to transparently cache single active record objects using memcached.
The purpose is to cache by fields that are being validated for unique values.
Cache gets refresh after save, and expire after destroy or after a logical delete.
It is less than 100 lines of code, so don’t be shy to look at the source for full understanding.
to_xls Plugin: Export to Excel in Rails the Easy Way
January 11th, 2009 by ary
Looking at the Google Analytics stats I realized that a lot of people are still reading my blog post about how to export to Excel in Rails.
IMO I prefer the csv method because it provides the same + more at no extra cost, but given people still wants xls files I wrote another rails plugin: to_xls.
UPDATE: SuperSaaS (Thanks!) mentioned that Excel does not interpret UTF8 characters in CSV files. So if that is a concern to you, maybe you should stick with XLS.
Using this plugin you don’t need the builder views, so it makes it as easy as the to_csv plugin I wrote. In fact it works the same.
In config/initializers/mime_types.rb register the custom mime type.
Mime::Type.register "application/vnd.ms-excel", :xls |
In the controller where you want to export to excel, add the format.xls line.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class UserController < ApplicationController def index @users = User.all respond_to do |format| format.html format.xml { render :xml => @users } format.xls { send_data @users.to_xls } end end def show... def new... def edit... def create... def update... def destroy... end |
That’s it!
Install
./script/plugin install git://github.com/arydjmal/to_xls.git |
TextAreaMate turns your textarea's into simple code editors
August 26th, 2008 by ary
TextAreaMate is a simple javascript library on top of Prototype, that turns a textarea into a simple code editor with a TextMate feeling.
For now it’s working on FF & Safari, Mac only. As soon as I get it to work cross-browser I will put it on GitHub for further development.
Features
tab key support
command + / for commenting lines
command + [ for indenting less (one line or a block of code).
command + ] for indenting more (one line or a block of code).
Dependencies
Prototype JavaScipt Library
Install
Get the beta here and copy both files to the appropriate directory.
Usage
Include prototype.js and textareamate.js:
1 2 |
<script src="prototype.js" type="text/javascript" charset="utf-8"></script> <script src="textareamate.js" type="text/javascript" charset="utf-8"></script> |
For railers, something like:
<%= javascript_include_tag :defaults, 'textareamate' %> |
Now you can start using it:
1 2 |
<textarea name="editor" id="editor" onkeydown="return TextAreaMate.onKeyPress(this,event)"> </textarea> |
It plays well with rails:
<%= text_area :pastie, :body, :onkeydown => 'return TextAreaMate.onKeyPress(this,event)' %> |
Demo
CSS Tip: Three-State Buttons
August 12th, 2008 by ary
Let’s say you have a text button that highlights when you hovered. You can add a third state, when clicked, by specifying a:active the same way you use a:hover. No javascript needed.
In your html:
1 2 3 |
<a href="#" class="button"> Some Text </a> |
In your css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
a.button:link, a.button:visited, a.button:hover { padding: 15px; text-decoration: none; color: #666; display:block; border-bottom: 1px solid #CCC; font-size: 12px; } a.button:hover { background-color: #F9F9F9; } a.button:active { background-color: #FFF; color: #333; } |
Demo
CSS Tip: Two-State Images
August 5th, 2008 by ary
Let’s say you have an image that when you hovered you want to highlight (ie. make it brighter). Instead of dealing with two different images you can just use opacity.
In your html:
1 2 3 |
<a href="#" class="image"> <img src="/some_image.jpg" /> </a> |
In your css:
1 2 3 4 5 6 7 8 9 10 11 |
a.image img { opacity: 0.60; -moz-opacity: 0.60; filter:alpha(opacity=60); } a.image:hover img { opacity: 1; -moz-opacity: 1; filter:alpha(opacity=100); } |
Demo
in_place_editing Plugin with validations!
July 22nd, 2008 by ary
I forked the in_place_editing plugin from Github and modified it so it validates your model before saving.
If you are interested, check it out.
to_csv plugin: Better Excel Compatibility
June 11th, 2008 by ary
A couple of days ago I blogged about how to export to MS Excel. I took an example from a client’s app, in which they are the final-users, and I know for sure they only use Excel 2003.
But if your app needs some sort of export feature, and you don’t know how the users are going to use the data, I would go with CSV. Why? As far as I know every spreadsheet app can open it, including Numbers and Office 2000 (which don’t handle XML-based xls files), plus they might use it with report tools unrelated to excel. And as a bonus it is much easier to use.
The Solution
Last night I wrote a very simple plugin called to_csv that gives you the ability to call to_csv to a collection of activerecords. The builder options are the same as to_json / to_xml, except for the :include.
Usage
1 2 3 4 5 6 7 8 9 10 11 |
@users = User.all # # defaults are export header and all fields except id, and timestamps # @users.to_csv @users.to_csv(:only => [:last_name, :role]) @users.to_csv(:timestamps => true, :id => true, :header => false) @users.to_csv(:except => [:last_name, :role]) @users.to_csv(:except => :role, :methods => [:name, :admin?]) |
Real life example
In the controller where you want to export to csv, add the format.csv line (as of rails 2.1 it is not necessary to register the csv myme_type)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class UserController < ApplicationController def index @users = User.all respond_to do |format| format.html format.xml { render :xml => @users } format.csv { send_data @users.to_csv } end end def show... def new... def edit... def create... def update... def destroy... end |
That’s it. No myme_type to register, no views to create, just install the plugin, and add format.csv { send_data collection.to_csv } to the controller’s respond_to block that you want to give export capabilities.
Install
./script/plugin install git://github.com/arydjmal/to_csv.git |
Ideas
I got ideas and influence from Mike Clarks recipe#35 in Rails Recipes book, some anonymous pastie, and whoever wrote to_xml/to_json builders.
Note
Does not work on a single activerecord, ie, User.first.to_csv. Cannot style output like xls.
Update
I modified the plugin so now it uses the fastercsv library instead of the old CSV library. SO if you don’t have the gem installed type:
sudo gem install fastercsv |
Export to Excel in Rails 2
June 8th, 2008 by ary
UPDATE: I released a Rails plugin that makes this much easier, http://arydjmal.com/2009/1/11/to_xls-plugin-export-to-excel-in-rails-the-easy-way.
Rails makes it super-easy to export anything to Excel. I took this example from a client’s project; they wanted to export to excel the data generated from orders/index.
I will summarize this in 3 simple steps:
First, you have to register the mime type in your config/initializers/mime_types.rb. This is needed for the respond_to block in the controller, and of course you have to do it only once.
Mime::Type.register "application/vnd.ms-excel", :xls |
Restart the server so the new configuration is loaded.
Now we are ready to respond in xls format; in this example http://localhost:3000/orders will render index.html.erb and http://localhost:3000/orders.xls will create a xls. So in the app/controllers/orders_controllers.rb we can have something like this:
1 2 3 4 5 6 7 8 |
def index @orders = Order.recent respond_to do |format| format.html format.xls end end |
Pretty clean, right? Finally, we need to create the excel file, and since Excel can read xml in the app/views/orders/index.xls.builder we have something like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8" xml.Workbook({ 'xmlns' => "urn:schemas-microsoft-com:office:spreadsheet", 'xmlns:o' => "urn:schemas-microsoft-com:office:office", 'xmlns:x' => "urn:schemas-microsoft-com:office:excel", 'xmlns:html' => "http://www.w3.org/TR/REC-html40", 'xmlns:ss' => "urn:schemas-microsoft-com:office:spreadsheet" }) do xml.Worksheet 'ss:Name' => 'Recent Orders' do xml.Table do # Header xml.Row do xml.Cell { xml.Data 'ID', 'ss:Type' => 'String' } xml.Cell { xml.Data 'Date', 'ss:Type' => 'String' } xml.Cell { xml.Data 'Description', 'ss:Type' => 'String' } end # Rows for order in @orders xml.Row do xml.Cell { xml.Data order.id, 'ss:Type' => 'Number' } xml.Cell { xml.Data order.date, 'ss:Type' => 'String' } xml.Cell { xml.Data order.description, 'ss:Type' => 'String' } end end end end end |
With this 3 easy steps you can give a export to xls any view.
So my export to excel link for the view would be:
link_to 'Export to Excel', formatted_orders_url(:xls) |
Now, the bigger reason I wrote this mini tutorial, was that this set-up gave me some trouble on IE. It was always rendering format.xls so my little-ugly-hack was to make sure that params[:format] is xls
1 2 3 4 5 6 7 8 |
def index @orders = Order.recent respond_to do |format| format.html format.xls if params[:format] == 'xls' end end |
Please, let me know if you have a better way to solve this problem.
Now, if you plan to have more than one xls view, I suggest to create this helper in app/helpers/application_helper.rb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
def excel_document(xml, &block) xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8" xml.Workbook({ 'xmlns' => "urn:schemas-microsoft-com:office:spreadsheet", 'xmlns:o' => "urn:schemas-microsoft-com:office:office", 'xmlns:x' => "urn:schemas-microsoft-com:office:excel", 'xmlns:html' => "http://www.w3.org/TR/REC-html40", 'xmlns:ss' => "urn:schemas-microsoft-com:office:spreadsheet" }) do xml.Styles do xml.Style 'ss:ID' => 'Default', 'ss:Name' => 'Normal' do xml.Alignment 'ss:Vertical' => 'Bottom' xml.Borders xml.Font 'ss:FontName' => 'Arial' xml.Interior xml.NumberFormat xml.Protection end end yield block end end |
So now the view would be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
excel_document(xml) do xml.Worksheet 'ss:Name' => 'Recent Orders' do xml.Table do # Header xml.Row do xml.Cell { xml.Data 'ID', 'ss:Type' => 'String' } xml.Cell { xml.Data 'Date', 'ss:Type' => 'String' } xml.Cell { xml.Data 'Description', 'ss:Type' => 'String' } end # Rows for order in @orders xml.Row do xml.Cell { xml.Data order.id, 'ss:Type' => 'Number' } xml.Cell { xml.Data order.date, 'ss:Type' => 'String' } xml.Cell { xml.Data order.description, 'ss:Type' => 'String' } end end end end end |
NOTE: This works with Office 2003+ for windows and Office 2004+ for Mac, it will not work with Office 2000, Numbers or QuickLook. So if this is a problem you could try another solution.
UPDATE: Check out my to_csv plugin for better excel compatibility!
What I've learned at RailsConf '08
June 8th, 2008 by ary
1) The value of open source.
Open source is really amazing. I’m looking forward to contribute to rails, and to write more plugins/gems. Why? It’s very probable that “your plugin (or whatever OSS)” it is going get better as more people use it or contribute to it. You will meet people, you’ll get your name out there, and a job opportunity may arise because of your results.
2) The value of hooking up with other programmers.
First it is fun to have friends like you. It’s also great to have close people to share knowledge, problems, etc. And again you might have job opportunities thanks to these relations.
3) How we (programmers) should work with designers.
There were great talks at RailsConf, but I think this is the only session that taught me something. It was great talk given by Ryan Singer of 37Signals, he is a designer, not a programmer. A lot of people misunderstood his talk, and the purpose of it, eventhough Ryan made it pretty clear. In a nutshell:
(DESIGNER – PHOTOSHOP + HTML/CSS + RAILS_SOURCE) + PROGRAMMER = SUCCESS
4) I’m not alone.
The rails community is getting bigger and bigger, it was incredible to see so many people at a conference.
Getting ready for my very first RailsConf
May 23rd, 2008 by ary
I’m really excited about this coming RailsConf, I’m certain that I’m going to meet a lot of talented people!
Can’t wait…
link_to_tagged_current
April 10th, 2008 by ary
Almost every site has some sort of tabbed navigation. There are a lot of alternatives of how to accomplish it. One way that comes to my mind is Paolo Dona’s widgets plugin. But sometimes I want something lighter, and link_to_unless_current is way too simple. So I created link_to_tagged_current, a very simple rails helper that in difference of link_to_unless_current, when current, it creates the link + it adds the class current to it.
In app/helpers/application_helper.rb
1 2 3 4 5 6 |
def link_to_tagged_current(name, options = {}, html_options = {}, &block) if current_page?(options) html_options[:class] = "#{html_options[:class].to_s} current".strip end link_to name, options, html_options, &block end |
After little use, this was still pretty simple, so I added a :highlights_on option.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
def link_to_tagged_current(name, options = {}, html_options = {}, &block) current = false highlights = html_options[:highlights_on] ? html_options[:highlights_on] + [options] : [options] highlights.each do |h| if (h[:controller] == @controller.controller_name and !h[:action]) or (h[:controller] == @controller.controller_name and h[:action] == @controller.action_name and !h[:id]) or (!h.kind_of?(Hash) and current_page?(h)) current = true break end end if current html_options[:class] = "#{html_options[:class].to_s} current".strip end html_options[:highlights_on] = nil link_to name, options, html_options, &block end |
Some usage examples are:
1 2 |
link_to_tagged_current 'Dashboard', dashboard_url link_to_tagged_current 'Users', users_url, :highlights_on => [:controller => 'admin'] |
Given this is a very common need I will try to push it to rails.
UPDATE: Rails core member Pratik said that it should stay as a plugin for now. You can see the ticket here.
error_message_for (not error_messages_for)
March 13th, 2008 by ary
Sometimes I want to print each error of a form right below the input/select box. And at the same time let the user know that there were problems.
If I use error_messages_for, I will be showing the user each error twice… not a good idea.
So for this case I wrote error_message_for, a method that tells you that there is something wrong whether you have 1 error or more. It also accepts more than one model.
1 2 3 |
def error_message_for(*args) "<p id='errorExplanation'>Oops, enter correct info.</p>" if args.any? {|o| error_messages_for(o).size > 0 } end |
Some usage examples are:
1 2 |
error_message_for :account error_message_for :account, :user |
Rails built-in timezones are awesome!
February 5th, 2008 by ary
You probably know that rails edge sports some very good goodies. But after using rails time zones, I was really amazed how they solved a not-so-fun “problem” like timezones.
Thank you for making my life easier!
Really looking forward to Rails 2.1.
