How to send email asynchronously using Devise and Rails3
Hello everyone.
I’d show a workaround to send email asynchronously using Devise and Rails3.
Suppose we have already up and running our application with Devise and delayed_job correctly installed.
A first attempt was to add in config/initializers the following file (devise_async.rb):
module Devise
module Models
module Confirmable
handle_asynchronously :send_confirmation_instructions
end
module Recoverable
handle_asynchronously :send_reset_password_instructions
end
module Lockable
handle_asynchronously :send_unlock_instructions
end
end
end
This workaround has worked in part: the send method has been properly enqueued in the database, but when delayed_job tries to fire the job, the following error is raised:
[Worker(host:stefano-desktop pid:13153)]
As you can see, the job is trying to call the wrong send method: send_confirmation_instructions_without_delay.
At this point, I’ve implemented an even more dirty hack, overriding Devise’e methods using the syntax specified by intridea to send emails in the background:
module Devise
module Models
module Confirmable
# Send confirmation instructions by email
def send_confirmation_instructions
generate_confirmation_token! if self.confirmation_token.nil?
::Devise.mailer.delay.confirmation_instructions(self)
end
end
module Recoverable
# Resets reset password token and send reset password instructions by email
def send_reset_password_instructions
generate_reset_password_token!
::Devise.mailer.delay.reset_password_instructions(self)
end
end
module Lockable
# Send unlock instructions by email
def send_unlock_instructions
::Devise.mailer.delay.unlock_instructions(self)
end
end
end
end
This solution, however, is too tied to the implementation of Devise and is therefore not a good one (besides being really really dirty).
The latest idea, which represents the solution I’ve used is implemented as follows: use the alias_method in this way:
module Devise
module Models
module Confirmable
alias_method :send_confirmation_instructions_without_delay, :send_confirmation_instructions
handle_asynchronously :send_confirmation_instructions
end
module Recoverable
alias_method :send_reset_password_instructions_without_delay, :send_reset_password_instructions
handle_asynchronously :send_reset_password_instructions
end
module Lockable
alias_method :send_unlock_instructions_without_delay, :send_unlock_instructions
handle_asynchronously :send_unlock_instructions
end
end
end
This latest hack works a treat; is not the best but let you send mail with Devise asynchronously.
If you have any better solutions, do not hesitate to share!
How to install MySQL and Rails on Osx Snow Leopard
Hello everyone.
These days I’ve bought a MacBook Pro with Osx Snow Leopard 64-bit pre installed.
Having to develop mainly in Rails and Django on MySQL and PostgreSQL, I’ve found some difficulties to install and properly configure all packages.
The main problems were due to the presence of 32bit libraries and other at 64bit. For example, Python or Ruby (already installed by default) were compiled at 32bit. Everything seems to work best, however, until you try to install the gem “mysql” or the eggs “psycopg2″ or “MySQL_python”.
These database drivers, having to be “compiled”, generate many problems of incompatibility between different architectures.
In this first tutorial, we’ll see how to install MySQL and Rails 3.0. In the next we’ll see how to proceed with Django and PostgreSQL.
The approaches taken by me are simply the result of googling and other online tutorials. So I’ll link every resource I’ve used.
Regarding the installation of MySQL, I’ve mainly followed the Hivelogic tutorial.
See below the key points that allowed a successful installation.
Step 1: Set the $PATH environment variable
Open a terminal and set the $PATH environment variable in order to link the correct folders in /usr/local/
Add, if it does not exist, this line at the bottom of the .profile file:
and reload the $PATH in this way:
To verify that our $PATH contains the paths set above, type the following command:
Step 2: Download MySQL
Create a new folder to download the sources and compile them:
cd ~/src
Download the latest version available at the time of writing this tutorial:
Step 3: Compile and Install
Build and install MySQL with the following commands:
cd mysql-5.1.47
./configure --prefix=/usr/local/mysql --with-extra-charsets=complex \
--enable-thread-safe-client --enable-local-infile --enable-shared \
--with-plugins=innobase
make
sudo make install
At this point we create a mysql user and a default database.
sudo ./bin/mysql_install_db --user=mysql
sudo chown -R mysql ./var
cd ..
Then we can create scripts to start and stop the MySQL server using the command line.
We create a bin folder in our home and the following file, also giving execute permissions:
touch mysqlscript
chmod +x mysqlscript
Edit the file you’ve just created by inserting the following body:
start()
{
echo -n "Starting MysSQL server"
cd /usr/local/mysql ; sudo /usr/local/mysql/bin/mysqld_safe
return
}
stop()
{
echo -n "Stopping MySQL server"
cd /usr/local/mysql ; sudo /usr/local/mysql/bin/mysqladmin -u root -p shutdown
return
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo "Usage: {start|stop|restart}"
exit 1
;;
esac
exit $?
At this point you can start the server by typing “mysqlsript start” in the console. To stop the server just type “mysqlscript stop”.
We are now able to install Ruby on Rails. As mentioned at the beginning of the article, system Ruby is compiled at 32bit.
If you want to compile from source at 64bit and place it in /usr/local/ ruby just follow this tutorial.
Since it is my intention to use instead rvm, I’ll settle for a system level Ruby at 32bit and I prefer to compile every new virtual environment at 64bit (from this tutorial)
Therefore proceed as follows:
Step 1: Install rvm
Launch in a console this command and follow the instructions:
Step 2: Install Ruby 1.9.2
Type the following commands and verify that you have version 1.9.2 installed.
rvm 1.9.2
ruby -v
Step 3: Create a Rails3 gemset
Create a Rails3 gemset and activate it as default:
rvm 1.9.2@rails3 --default
Step 4: Install Rails3 and database drivers for SQLite and MySQL
env ARCHFLAGS="-arch x86_64" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
gem install rails
In this tutorial we’ve then installed MySQL and Ruby 1.9.2 from source. Now that all the packages have been compiled to 64bit we should not find errors while installing other application’s gems.
The top 20 plugins to create a Rails application
Rails is now closer to its official third release and all plugins and gems authors are working to ensure compatibility of their products with the new version of the framework.
Among the many Rails plugins released by the community, I make a list of 20 most used (and useful) in our projects at DevInterface.
Authentication
- Authlogic: this plugin is definitely the more common among Rails 2.x applications. It was releases as release replacement for the powerful but verbose “RESTful Authentication” http://github.com/technoweenie/restful-authentication, pioneer of Rails authentication during the 1.2.x version.
- Devise: provides a complete implementation of all authentication problems with support for sign up, password recovery and more. Its modularity, combined with the fact of being Rack based, candidates this plugin to become the reference for authentication in Rails 3.
- Subdomain_fu: great plugin for managing subdomains. Take a look at our authlogic_subdomain_fu_startup_app to get an idea of how it works together with Authlogic. Rails 3 provides native support for conditional routing based on subdomains, so this feature of the plugin will be removed in future versions.
User Interface
- LessCSS is a library that essential gives a way to write stylesheets quickly and DRY. The syntax provided by this framework allows to define variables and to include other existing chunks of style. It’s also perfectly compatible with the CSS syntax, so just rename the css file into a .less one to be already half done.
- More: This plugin allows you to automatically use LessCSS in Rails applications. Together with Blueprint CSS allows the development of templates in a agile and cross-browser way.
- HAML and “Sass” http://sass-lang.com/ represent an alternative to ERB templating by giving the possibility to write HTML pages in a concise and fast way. As well as LessCSS, Sass provides an excellent solution to quickly write CSS with a concise and reusable syntax.
- Formtastic: plugin that allow you to build forms for your model in an elegant and functional way. Note that the plugin automatically translates the labels of attributes using the language file associated with ActiveRecord.
- Show_for is the complementary of Formtastic to view our models details in “show” pages.
- Paperclip: great plugin for handling attachments and well handled by Formtastic.
Business Logic
- Inherited Resources is an excellent plugin for writing controllers quickly and DRY. The use of this plugin will left our controller classes a little “empty” …
- Active Scaffold: this plugin is useful especially to manage the CRUD of any models in the administration pages of the site. It’s easy to configure and offers a great versatility to handle all situations.
- CanCan is a small plugin for managing ACL (access control list) quickly and easily. Useful if you want to restrict access to resources without the need to build a more complex solution.
- Will_paginate: a must for anyone who wants to paginate his dataset.
Miscellaneous
- Configatron: With this plugin you can configure application parameters without constants or global variables.
- Delayed Job, plugins that can handle long asynchronous processes that run in the background. Useful for newsletter management.
Testing
- Cucumber: large library for developing Rails applications following the BDD (behaviour driven development). It ’s a great tool if used continuously and extensively, but requires a bit high learning curve. You could easily duplicate features and steps if you have no knowledge of what has already been implemented by other team members.
- RSpec represented a revolution in the world of testing for the Rails community, shifting the focus from TDD (test driven development) to BDD. Excellent to test models and controllers. The stories have been replaced by Cucumber’s features.
- Shoulda: plugin, originally created to apply BDD in Test::Unit classes, that perfectly fits into RSpec and very useful for testing of models.
- FactoryGirl, plugin created as an alternative to the verbose and not very maintainable fixtures.
- Mocha: needed to make the tests decoupled from the database, provides a clean syntax to create stubs and mock of our models.
This is only a short list of the most useful plugins available. Probably someone will choose some others for his top 20, someone else will agree with me. What do you think?
Please share your preferences.
How to implement a viewing system in Rails
Hello everyone.
Today I will show how to implement a viewing system for any model of your Rails application.
Suppose we have a model News and we would like to keep track of how many times a single news has been displayed, in order to implement box like “the most ’seen’” etc..
Suppose we have a model News created in this way:
myapp/db/migrate/001_create_news.rb:
def self.up
create_table :news do |t|
t.string :title
t.text :content
t.date :online_date_start, :null => true
t.date :online_date_end, :null => true
t.boolean :online, :null => false, :default => true
t.timestamps
end
end
def self.down
drop_table :news
end
end
myapp/app/models/news.rb:
validates_length_of :title, :within => 2..255
validates_presence_of :title, :content, :online_date_start
end
The basic idea is to increment a counter displayed every time a user views the news.
Some considerations:
an implementation of this type would allow a user to press the refresh button and constantly increase the counter.
So the goal is to have a clever mechanism that increases the counter:
- 1 once for each registered user
- 1 only once per IP in the case of guest
We would also like that this mechanism could be applied not only to model News, but to any model of our application.
Then we create the migration of our model Viewing:
myapp/db/migrate/002_create_viewings.rb:
def self.up
create_table :viewings do |t|
t.string :ip
t.string :viewable_type
t.integer :viewable_id
t.references :person
t.datetime :created_at
end
end
def self.down
drop_table :viewings
end
end
and the corresponding model:
myapp/app/models/viewing.rb:
# RELATIONSHIPS
belongs_to :viewable, :polymorphic => true, :counter_cache => :popularity
belongs_to :viewer, :class_name => "Person", :foreign_key => "person_id"
# VALIDATIONS
validates_uniqueness_of :ip, :scope => [:viewable_id, :viewable_type, :person_id]
validates_uniqueness_of :person_id, :allow_nil => true
# OTHER
def viewable_type=(sType)
super(sType.to_s.classify.constantize.base_class.to_s)
end
end
As you can see, the model Viewing is not closely tied to model News, but given its polimorphic nature, it may be associated with any model.
At this point, we can associate the model Viewing to the News :
myapp/app/models/news.rb:
validates_length_of :title, :within => 2..255
validates_presence_of :title, :content, :online_date_start
has_many :viewings, :as => :viewable
end
and add the column “counter cache to the table News:
myapp/db/migrate/003_add_popularity_to_news.rb:
def self.up
add_column :news, :popularity, :integer, :default => 0
end
def self.down
remove_column :news, :popularity
end
end
Now we have everything necessary to implement the mechanism for viewing in our model News.
Let’s show how to increment the counter to “show” of the news.
myapp/app/controllers/news_controller.rb:
after_filter :record_view, :only => :show
def show
@news = News.find(params[:id]
end
private
def record_view
@news.viewings.create(:ip => request.remote_ip, :viewer => current_user) unless @news.nil?
end
end
Rails Authlogic + Subdomain_fu Template
The second free Rails startup skeleton written by DevInterface and releases under Rails MIT license is Rails Authlogic + Subdomain_fu Template.
Rails Authlogic + Subdomain_fu Template
This template works as a skeleton for any new Rails application (using Rails 2.3) that aims to provide authentication with subdomain support.
To install and run this template perform following actions:
cp config/database.yml.example config/database.yml
rake gems:install
rake gems:install RAILS_ENV=test
rake db:migrate
Skeleton Behaviour
This template sets up a working application with support for authentication and subdomain.
Application workflow
- Guest access a public section of the site (http://localhost:3000)
- Guest chooses to register new account (http://localhost:3000/account/new), including itself as user, and becomes account’s owner
- Accounts owner goes to his account (subdomain) url (http://useraccount.localhost:3000/login) and logs into his account
- Accounts owner can add more users to it’s account (http://useraccount.localhost:3000/users/new)
- Each created user can log into the account they belong
Skeleton features
Here’s a list of what this template sets up:
Rails
Javascript
- jQuery as javascript framework instead of prototype
CSS
- Blueprint as css framework
Testing
- BDD testing support using RSpec, Cucumber, and FactoryGirl
Other
Some other useful gems/plugins such as:
Rails Startup Template
Hi all.
Today I would like to show the first of two free Rails startup applications written by DevInterface.
They are both hosted on GitHub and releases with Rails MIT licese. So feel free to clone/fork/patch them.
Rails Startup Template
This template lets you to create quickly new Rails applications using Rails 2.3. To use it, just specify the -m switch when creating a Rails application:
Generated Application
Here’s a list of what this template sets up:
SCM
* git repository
Javascript
* Choice of Prototype or jQuery
CSS
* Blueprint as css framework
Rails
* Choice of Authlogic with or without OpenID support (includes models, controllers and views)
Testing
* BDD testing support using RSpec, Cucumber, and FactoryGirl
Other
Some other useful gems/plugins such as:
How to highlight source code using Ultra Violet and Hpricot
Hi, in this tutorial I want to show how to highlight source code using Ultra Violet and Hpricot
- Installation:
Hpricot installation is very easy and it doesn’t require any special knowledge. Just follow instructions here.
Ultra Violet installation: follow installation.
If you are using Ubuntu 8.10 you’ll probably found some errors due to the Oniguruma dependency.
To install correctly this library just follow the instruction found here and here
- Requirements:
Highlight source code between
tags in a description field.
- Solution:
Suppose to have a Snippet model with a
field and an
field.
Just add a
filter with the following implementation:
def highlight_description
h = Hpricot(self.description)
h.search('//code') do |e|
e.inner_html = Uv.parse(e.inner_html, "xhtml", "ruby", false, "all_hallows_eve")
end
self.description_html = h.to_html
end
Rails performances
Uno degli aspetti piu’ importanti riguardanti lo sviluppo di un’applicazione web riguarda sicuramente l’ottimizzazione delle sue prestazioni.
Ottimizzare le prestazioni significa rendere disponibili i risultati della richiesta nel minore tempo possibile.
Due sono gli aspetti cruciali che entrano in gioco ad ogni richiesta dell’utente:
* la computazione della richiesta lato backend, con accesso al database ed il recupero dei dati
* il rendering della pagina di risposta
In questi giorni ho iniziato a tenere sotto controllo le performance della mia applicazione in via di sviluppo: non disponendo del grande budget necessario a garantirle un server dedicato, ho bisogno di ridurre al minimo le latenze, in modo da garantire dei tempi di risposta dignitosi in uno shared hosting con 120 MB di memoria.
Una delle prime azioni e’ stata ottimizzare le query necessarie a recuperare i dati da mostrare in pagina.
Molto spesso infatti capitava di eseguire nella action una find del tipo
e nella view ciclare
per visualizzarne i concerti.
Tutto questo al costo di n+1 accessi al database.
La soluzione adottata consiste nell’eager loading, cioe’ recuperare con un’unica query sia l’artista che i suoi concerti:
Una seconda ottimizzazione e’ stata sostituire nelle pagine le occorrenze di
con
evitando cosi’ un’ulteriore accesso al database.
Con queste ottmizzazioni, sono riuscito a garantire una riduzione dei tempi di risposta del 40% circa.
Tutto questo non e’ pero’ abbastanza per rendere la mia applicazione performante e scalabile.
Nonostante i miglioramenti apportati, nel caso in cui piu’ utenti richiedono la stessa pagina, per ciascuno l’azione accedera’ al database per calcolare i medesimi risultati.
Per evitare questo spreco di risorse, e’ necessario utilizzare dei meccanismi di caching.
Rails mette a disposizione dello sviluppatore tre meccanismi di caching:
* page caching
* action caching
* fragment caching
Non mi dilungo con la descizione dettagliata di questi meccanismi, in quanto gia’ trattata da innumerevoli altri articoli, come:
Riassumendo la loro utilita’, si puo’ affermare che il page caching e’ sicuramente il piu’ performante, in quanto viene servita all’utente una pagina html statica senza dover passare attraverso il controller di Rails.
Questo meccanismo e’ indicato per servire pagine che rimangono prevalentemente invariate nel corso del tempo e servibili a tutti gli utenti indifferentemente.
L’ action caching e’ meno veloce della precedente, in quanto il risultato dell’azione viene cacheato, ma tutti i before e after filters vengono comunque invocati.
Questo tipo di caching e’ invitante quando si devono servire pagine ristrette ad utenti loggati o con un particolare ruolo.
Il terzo tipo di caching fornisce invece allo sviluppatore un grado di liberta’ maggiore, dandogli la possibilita’ di cacheare piccoli frammenti di view, a scapito pero’ delle prestazioni.
La mia applicazione, come ogni social network, presenta un layout personalizzato in base alla presenza di un utente autenticato o meno.
Questo aspetto in un primo momento mi ha fatto scartare il page caching (ovviamente) e l’action caching, facendomi concentrare sul fragment caching.
Purtroppo, il guadagno in prestazione del fragment caching e’ veramente irrisorio se la action deve comunque computare dei risultati necessari per la personalizzazione della pagina.
La soluzione adottata infine e’ stata l’utilizzo della conditional cache
Questo plugin permette di appendere al frammento di cache una stringa custom:
def cache_tag
if logged_in?
return '-' + current_user.to_param
else
return '-guest'
end
end
#User.rb
def to_param
"#{id}-#{login.gsub(/[^a-z1-9]+/i, '-')}"
end
In questo modo, sono riuscito a produrre frammenti di cache personalizzati per ogni utente e per visitatori guest.
Per intenderci, la action show di un artista (artistxx, id 1) produrra’ questi frammenti:
1-artistxx-guest.cache per tutti i visitatori non autenticati
1-artistxx-3-stefano.cache per lo user stefano con id 3
1-artistxx-4-pippo.cache per lo user pippo con id 4
Quindi, la prima volta che un utente visualizzara’ la pagina show dell’artista artistxx la action verra’ computata interamente, per tutte le successive verra’ usata la cache.
Un approccio di questo tipo ha comportato un grande lavoro per gestire lo sweeping (a suon di espressioni regolari
) in seguito a create, update o destroy dei vari modelli.
L’utilizzo di una cache personalizzata di queto tipo mi ha permesso di abbattere i costi di computazione delle action.
Il mio unico dubbio deriva dalla proliferazione di frammenti di cache sul filesystem: non vorrei che a lungo andare l’accesso al filesystem potesse diventare un collo di bottiglia.
Purtroppo, per il momento non posso dare una risposta valida a questo interrogativo, dal momento che l’applicazione e’ ancora in sviluppo.
Dal mio punto di vista, mi pare di aver comunque scelto l’approccio migliore…
Rails e transazioni
In questi giorni ho toccato con mano la gestione delle transazioni in Rails.
Il mio problema consisteva nel gestire in un’unica transazione la crezione di due modelli diversi ed indipendenti l’uno dall’altro.
Ogni oggetto ActiveRecord e’ provvisto di un metodo
, in grado di gestire in blocco operazioni di scrittura sullo stesso o su oggetti collegati da relazioni tipo
ecc. Quindi, nel mio caso, creare due oggetti non relazionati significava aprire due transazioni separate.
Questo aspetto di Rails mi ha molto stupito e sinceramente non capisco la scelta di THH di gestire le transazioni in questo modo.
A mio parere, una scelta piu’ felice e’ stata presa dal team di Django, dando la possibilita’ di gestire le transazioni alla Rails o relative all’intera richiesta HTTP, attraverso la libreria
. Questa libreria permette infatti di aprire una transazione con l’inizio di una richiesta HTTP e di committare o di eseguire il rollback in base al successo o no della
Tornando al mio problema, a nulla sono valsi i tentativi di risolvere la transazione usando:
ActiveRecord::Base.transaction do
@first_model = FirstModel.new(params[:first_model])
@first_model.save!
@second_model = SecondModel.new(:user => current_user, :first_model => @first_model)
@second_model.save!
end
rescue Exception => @ex
# handle the exception
end
oppure usando transazioni innestate:
FirstModel.transaction do
SecondModel.transaction do
@first_model = FirstModel.new(params[:first_model])
@first_model.save!
@second_model = SecondModel.new(:user => current_user, :first_model => @first_model)
@second_model.save!
end
end
rescue Exception => @ex
# handle the exception
end
In entrambi i casi, se la creazione di
falliva, per la prima transazione relativa al
non veniva eseguito il rollback, e i dati venivano salvati comunque sul database.
La soluzione al problema e’ stata incapsulare l’intero motodo del controller in un
, aprendo una transazione prima dell’esecuzione del metodo e chiudendola all’uscita dello stesso.
Questo il codice:
prepend_around_filter :transaction_filter
def transaction_filter
ActiveRecord::Base.transaction { |*block_args| yield(*block_args) if block_given? }
end
Un’alternativa potrebbe essere l’utilizzo del plugin Super Transaction
Rails Plugins
Una delle feature piu’ interessanti di Rails e’ senza dubbio il meccanismo dei plugin.
L’utilizzo di plugin permette infatti di estendere la propria applicazione aggiungendo in modo quasi trasparente funzionalita’ nuove sviluppate dalla comunita’ intorno a Rails.
Ecco una lista dei plugin indispensabili che ogni web application dovrebbe avere:
GENERALE:
* RESTful authentication
* Acts As Taggable On Steroids
BLOGGING:
GEOCODING:
* GeoKit
* YM4R/GM
ECOMMERCE:
TEMPLATING:
* Liquid