This article explains how you can use Zoho to send emails in your Rails application. Zoho provides a lite package that offers 5 user accounts each with 5 GB storage. So it is a good start for a small website.

I tried to set up mail sending with Zoho using action mailer with below settings.

  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    address:                'smtp.zoho.com',
    port:                      465,
    user_name:              'support@investingnote.com',
    domain:                 'example.com',
    password:               'password',
    authentication:         :plain
  }
  config.action_mailer.default_url_options = { host: 'localhost:3000' }

When I try to send emails, it took around half a minute and throw the exception Net::ReadTimeout.

This may be caused by the Zoho server ignores the connection because it requires secure connections like SSL/TLS. FastMail’s article provides a very good explanation in the mail server/client communications and SSL/TLS and Starttls. Below are some exacts. 

  • SSL and TLS both provide a way to encrypt a communication channel between two computers (e.g. your computer and our server). TLS is the successor to SSL and the terms SSL and TLS are used interchangeably unless you’re referring to a specific version of the protocol.
  • STARTTLS is a way to take an existing insecure connection, and upgrade it to a secure connection using SSL/TLS. Note that despite having TLS in the name, STARTTLS doesn’t mean you have to use TLS, you can use SSL.

Standard SMTP uses 25, on the configuration we are using port 465. From here, we can tell that we might need to provides the SSL or TLS as an option. Below is modified configuration.

  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    address:                'smtp.zoho.com',
    port:                      465,
    user_name:              'support@investingnote.com',
    domain:                 'example.com',
    password:               'password',
    authentication:         :plain,
    ssl:                    true,
    tls:                    true,
    enable_starttls_auto:   true
  }
  config.action_mailer.default_url_options = { host: 'localhost:3000' }

However, it still throws EOFError sometimes when sending email. I am using devise for authentication. Under config/initializers/devise.rb, there is one line specified the sender.

config.mailer_sender = 'no-reply@example.com'

When I specify the sender as no-reply@example.com which I don’t really create on the Zoho mail server, the mail server doesn’t send back correct message and action mailer EOFError is thown.

EOFError (end of file reached): 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/buffering.rb:174:in `sysread_nonblock' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/buffering.rb:174:in `read_nonblock' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/protocol.rb:153:in `rbuf_fill' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/protocol.rb:134:in `readuntil' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/protocol.rb:144:in `readline' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/smtp.rb:931:in `recv_response' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/smtp.rb:917:in `block in getok' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/smtp.rb:941:in `critical' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/smtp.rb:915:in `getok' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/smtp.rb:909:in `quit' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/smtp.rb:615:in `do_finish' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/smtp.rb:522:in `ensure in
start' 
/Users/Shanison/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/smtp.rb:522:in `start'  mail (2.5.4) lib/mail/network/delivery_methods/smtp.rb:112:in `deliver!'

To fix the problem, you have to use an email account that does actually exists. I created an account support@example.com instead of no-reply@example.com. Although we tell users don’t reply, it is better we create a real email account, which we can used to track the email sent.


Two more things, Starttls is designed to use one port as normal IMAP/POP/SMTP. So it can upgrades if the server requires it. We can remove the “starttls: true” configuration as we know the port is from standard port, but it makes no difference. Remember to change the default_url_options in your production.rb.

  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    address:                'smtp.zoho.com',
    port:                      465,
    user_name:              'support@investingnote.com',
    domain:                 'example.com',
    password:               'password',
    authentication:         :plain,
    ssl:                    true,
    tls:                    true
  }
  config.action_mailer.default_url_options = { host:  'localhost:3000' }

Ruby on Rails has changed a lot these few years. There are some security issues found recently. One of them is regarding the vulnerability in the JSON parser that comes with Active Support. You can read more here. However, the patch provided is only available for Rails 2.3.x and 3.0.x. I checked the code for Rails 2.2.2 and found that this version is affected as well. Without the official patch, I have to come up with my own patch for that. This is a serious problem if your application is not up to date with Rails. I developed a Ruby on Rails website that provides stocks information about three years ago with a small team, which stayed with Rails 2.2.2. Now it is time to upgrade it to the latest Rails 3.2.12. Below is how I did it and some of the major changes that has to be made in the code.

 

The whole project structure has changed quite a lot between Rails 2 and Rails 3 especially with the introduction of asset pipeline and bundlers. The easier way to upgrade your apps is to create a blank new Rails 3 apps and move in all the new folders into your old Rails 2 apps. For the files with the same names under same directories e.g. config/environments.rb, config/environments/production.rb, there are some API/format changes, so you need to compare the contents and see how to merge them. After you have done that, you can try to start your rails applications, which I believe the server can’t even be started. You should check every single error messages shows up in the console and fix them one by one until everything is fine. Below are some major changes that I met with.

 

  1. For the app/controllers/application.rb, it should be named as application_controller.rb now. Otherwise ‘uninitialized constant ApplicationController’ would be thrown.
  2. ENV['RAILS_ENV'] is now deprecated, use Rails.env instead.
  3. Rails.root class used to be String. Now it is changed to PathName. So you can’t do things like below:
    File.read(Rails.root + "/config/streaming_config.yml")
  4. lib folders are not auto loaded. So you will see some missing constant errors. To auto load the lib folders add below two lines to the config/application.rb.
    config.autoload_paths += %W(#{config.root}/lib)
    config.autoload_paths += Dir["#{config.root}/lib/**/"]
  5. filter_parameter_logging is no longer available. To filter out the parameters you can do it in the config/application.rb.
    config.filter_parameters += [:password]
  6. You cannot access controller methods in the view with @controller anymore. You have to use controller instead.
  7. For action view rendering, you no longer need to call h(string) to escape HTML output, it is on by default in all view templates. In Rails 2 you need to do below to escape the parameters, if not, you are vulnerable for XSS attacks.
    <%= h @params[:user_name] %>

    In Rails 3, this html escape is on by default. However if the variable or contents you are trying to render contains html, and you want to render the html you have to explicitly call raw methods or html_safe method.

    <%= raw @page.content %>
    <%= @page.content.html_safe %>

    I forget to put raw or html_safe in some of the views, and it renders escaped html instead. So you may want to check across the whole site to make sure everything is alright.

  8. For form_tag and form_for, you need to use <%= %> instead of <% %>, otherwise the form won’t be rendered at all.
  9. will_paginate 2 won’t work with Rails 3. Have to upgrade to will_paginate 3 otherwise uninitialized constant ActiveRecord::Associations::AssociationCollection error will be thrown.
  10. Array.paginate will throw error.The Array#paginate method still exists, too, but is not loaded by default. If you need to paginate static arrays, first require it in your code: require ‘will_paginate/array’
  11. For active record, save(false) changed to
    save(:validate => false)
  12. request.request_uri changed to request.url
  13. REXML::Document is not auto loaded, need to explicitly require it before using.
    require 'rexml/document'
  14. rake API changes. The :needs => :environments is deprecated. In Rails 2 :
    task :task_name, :argument_name, :needs => :environment do |t,args|
        # ...
     end

    In Rails 3, you have to do the following:

    task :task_name, [:argument_name] => :environment do |t,args|
        # ...
     end
  15. params[:path] used to be an array of the path split by slash. e.g. you might see the value as ['user', 'details.html'], now it is a string /user/details. Note that params[:path] doesn’t contains the format.
  16. interpreate_status is not in use any more. You can use Rack::Utils::HTTP_STATUS_CODES[status_code] to do the same thing.
  17. Mailer API changes. In Rails 2, you would call deliver_welcome_email or create_welcome_email. This has been deprecated in Rails 3.0 in favour of just calling the method name itself. So you can call Mailer.welcome_email.
  18. Mail API changes. In Rails 2 you define a mailer like below (this example is copied from rails guide)
    class UserMailer < ActionMailer::Base
      def welcome_email(user)
        recipients    user.email
        from          "notifications@example.com"
        subject       "Welcome to My Awesome Site"
        sent_on       Time.now
        body          {:user => user, :url => "http://example.com/login"}
      end
    end

    However in Rails 3 above codes has to be changed to below:

    class UserMailer < ActionMailer::Base
      def welcome_email(user)
        @user = user
        @url =  "http://example.com/login"
        mail(
            :to            => user.email
            :from       =>    "notifications@example.com"
            :subject    =>   "Welcome to My Awesome Site"
            :date        =>       Time.now
        )
      end
    end
  19. If a action name is not defined in the controller but the corresponding views file exists, in Rails 2, it will call method_missing. However in Rails 3, it won’t call method_missings. Thus in the help controller we can’t use the method_missing to dynamic rendering the views.

 

I attended the Red Dot Ruby Conference this year at NUS University Cultural Centre last Friday and Saturday. It was a two days event and attracted approximately 200 programmers around the world.

Llya Grigorik from google gave a very interesting talk on how to build a faster web using various technics. If you are experiencing slow website problem, you may want to check out his slides at Building a Faster Web.

There are also a lot of interesting topics that were discussed during the conference e.g PUBSUB infrastructure, Client Slide Templating, Using Redis to improve site performance, CoffeeScript etc.

Red Dot Ruby Conference 2012

Red Dot Ruby Conference 2012

Cross Domain Ajax Request is something that is prohibited by the browser becomes it violates the Same Origin Policy. According to wikipedia, the term “origin” is defined using the domain name, protocol, port number. Two resources are considered to be the same origin if and only if all these values are exactly the same. This also implies that even if the two resources are in different subdomains, it is not allowed as well.

In order to do cross domain ajax request, there is one way to do it using JSONP. JSONP, which is short for “JSON with padding” is a complement to the base JSON data format. It provides a method to request data from a server in a different domain. This is viable because there is no restriction on including third party javascript files in the website. So here is how it works. E.g. you are requesting a server http://sampleserver.com/sampledata.json to return the following json

{ "name" : "Shanison" }

Instead of directly requesting this using XMLHttprequest, you use javascript to insert a script tag in the html,

Now the browser would send the requests and download the response, but the problem is that the response is JSON instead of javascript. So the trick here is that for server instead of returning JSON, it returns a function call with the JSON:

callBack({ "name" : "Shanison" })

After the javascript is downloaded, it will call the method callBack, which will takes the JSON as a parameter. Inside this callBack method, you can get the response of the JSON and do what ever you want.

So if you are using RAILS and JQuery, here is what you can do. Jquery provides a way to directly call ajax with JSONP as requested dataType and you don’t have to do the things as create a call back methods and create the script tag and inserted into the html. If you use jQuery, this is what you normally do ajax Request:

    $.ajax({
      url     : 'http://sampleserver.com/sampledata.json',
      type    : 'GET',
      dataType:  'json',
      success : function (response) {
        if (response['success'])
        {
          loadData(response['html']);
        }
      }
    })

To change it to use jsonp, you just need to change the dataType to ‘jsonp’, everything else remains the same. Jquery will do the magic I described for you. At the same time, it will send a parameter ‘callback’ to the server, which is the call back methods name that is generated by jQuery, it is a random name.

    $.ajax({
      url     : 'http://sampleserver.com/sampledata.json',
      type    : 'GET',
      dataType:  'jsonp',
      success : function (response) {
        if (response['success'])
        {
          loadData(response['html']);
        }
      }
    })

Now the only thing needs to be changed is on the application server. The application needs to make sure the response can return JSONP instead of JSON. If you are using Rails, to render the response in JSON, you usually do:

render :json => {:success => true, :html => prices_html}

To render the response with JSONP, which would wrap the JSON with the callback method submitted by the javascript:

render :json => {:success => true, :html => prices_html}, :callback => params[:callback]

With all this, you should be able to do Cross Domain Ajax Request using jQuery.

I love Rails Console. If there is anything wrong with my Rails application, I can simply fire the console, and debug from there. Rails makes the query to db very simple and elegant by providing us the ActiveRecord. However, sometimes you may want to know the underlying raw sql statement being sent to the database to see if there is any problem. Especially your rails app is being quite slow, you may want to check if this could be the problem.


So you know that under development mode, the log would print out the raw sql statements executed. What about Rails Console. By default, if you typed in any code that queries the database, it would simply return the objects back to you. You can do the following in order to show the raw sql statements:


Immediately after you have entered Rails Console, typed in the following code in console:


ActiveRecord::Base.logger = Logger.new(STDOUT)

After that, it should print out the sql queries.