by Doug Selph on June 2, 2010
I’ve been working on a project using beta 3 of Rails3, and was looking to use tabs from the jQuery UI project. Having run across a post featuring a TabsRenderer helper class, I thought I’d give it a whirl. The code from that post was written in 2008, and it did not work with the beta of Rails3, so I set out to see if I could get it working.
The original code for the helper class, when executed in Rails3, was rendering escaped HTML for the tab bodies, and nothing for the tab headers. Simply changing the call in the view to tabs.render to this:
tabs.render.html_safe
didn’t do the trick for unescaping the tab bodies. What ended up working was using this for the TabsRenderer class:
class TabsRenderer
def initialize(template, options={})
@template = template
@options = options
@tabs = []
end
def create(tab_id, tab_text, options={}, &block)
raise "Block needed for TabsRenderer#CREATE" unless block_given?
@tabs << [tab_id, tab_text, options, block]
end
def render
content_tag(:div, (render_tabs.html_safe + render_bodies.html_safe), {:id => :tabs}.merge(@options))
end
private # ---------------------------------------------------------------------------
def render_tabs
content_tag(:ul, render_headers.html_safe)
end
def render_headers
@tabs.collect do |tab|
content_tag(:li, link_to(content_tag(:span, tab[1]), "##{tab[0]}") )
end.to_s
end
def render_bodies
@tabs.collect do |tab|
content_tag(:div, capture(&tab[3]), tab[2].merge(:id => tab[0]))
end.to_s
end
def method_missing(*args, &block)
@template.send(*args, &block)
end
end
Everything else about the sample code on the original post can be used as originally presented.
Hope this helps you as you adjust to Rails3!
by Doug Selph on May 21, 2009
I recently had a need to validate email addresses submitted to a Rails application. I found several plugins/gems that could help with the task, and eventually settled on one. Then I had to figure out how to actually integrate that gem with the validation process of ActiveRecord. As has often been the case in my experience with Rails, once I figured it out it was incredibly easy, but it was less obvious on the front-end how to go about doing what I needed. So let’s begin…
I settled on using the email-veracity gem by Carsten Nielsen for validations. It is available from the gem site at github.
sudo gem sources -a http://gems.github.com
sudo gem install heycarsten-email-veracity
Great. Now I was able to play around with validating emails from irb, but what about in my app? Hmm…
I started digging around in the source code for the ActiveRecord class, wondering how I might create my own validation macro to use email-veracity. That was going ok until I couldn’t figure out how to access the error collection for my ActiveRecord object. Thankfully, that sent me back to scouring the web for a lead on another way to skin this cat.
Now with a fresher mind than when I’d last been in the ActiveRecord source, I looked around some more and took a close look at the validates_each macro. This is what I wound up with.
Note: You can get cleanly formatted copies of the code excerpts below from gist.github.com.
class Customer < ActiveRecord::Base
# EmailVeracity is used to validate email addresses submitted
require ‘email_veracity’
…
validates_each :email_address, :on => :save \
do |record, attr, value|
# create new Address object from string param
address = EmailVeracity::Address.new(value)
# Add to errors collection unless address is valid
record.errors.add attr, \
’- Does not appear to be a valid email address’ \
unless address.valid?
end
end
This gives basic validation as to format of the address supplied. Now, in another model, I wanted to confirm that the address not only was of good form, but that the domain in the email address belonged to the customer’s domain as recorded in the database.
class Email < ActiveRecord::Base
# EmailVeracity is used to validate email addresses submitted
require 'email_veracity'
validates_each :email_address do |record, attr, value|
# create new Address object from string param
address = EmailVeracity::Address.new(value)
if address.valid?
# Parse out domain from address
domain = address.domain
# Is domain in database on customers account?
domain_count = Domain.count(:conditions => \
”domain_name = ‘#{domain}’ and customer_id = \
#{record[:customer_id]}”)
record.errors.add attr, \
’- The email address submitted is on a domain \
which is not linked to your customer account’ \
unless domain_count > 0
else
record.errors.add attr, \
’- Does not appear to be a valid email address’ \
unless address.valid?
end
end
end
Is this a perfect solution? There will be varied opinions on that question. It is a working solution, but comes at the price of adding EmailVeracity to those of your ActiveRecord instances where you want to validate email addresses. You’ll have to judge whether that tradeoff is a reasonable one for your application.
EmailVeracity can do many other things, including finding the MX hosts for a given address’s domain name. Now you’re talking about an operation that necessitates a network call, which could fail or timeout, so you typically would not want to include such methods in a validation sequence.