Showing posts with label Rails. Show all posts
Showing posts with label Rails. Show all posts

Thursday, December 20, 2012

Ruby on Rails documentation

YARD
Yay! A Ruby Documentation Tool

http://yardoc.org/

http://rubydoc.info/docs/yard/file/docs/GettingStarted.md
http://rubydoc.info/docs/yard/file/docs/Tags.md#taglist

(rake doc:app hanged on processing one of the class)

Monday, December 3, 2012

Rails migration by sql statement directly


Sometimes you need to do something in SQL not abstracted directly by migrations:
class MakeJoinUnique < ActiveRecord::Migration    
def up      
execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"    
end      
def down      
execute "ALTER TABLE `pages_linked_pages` DROP INDEX `page_id_linked_page_id`"    
end  
end

Wednesday, November 14, 2012

Rails - Rails console useful tips

[8] pry(main)> app.class
=> ActionDispatch::Integration::Session
[9] pry(main)> app.users_path
=> "/users"
[10] pry(main)> app.root_url
=> "http://www.example.com/"
[11] pry(main)> app.new_user_session_path
=> "/user/sign_in"
[14] pry(main)> app.get '/users'
=> 302
[15] pry(main)> app.response.body.length
=> 101

app.get
app.post
app.put
app.delete

[13] pry(main)> helper.class
=> ActionView::Base

[17] pry(main)> "".methods.grep(/case/).sort
=> ["camelcase",
 "casecmp",
 "downcase",
 "downcase!",
 "swapcase",
 "swapcase!",
 "titlecase",
 "upcase",
 "upcase!"]

[18] pry(main)> all_users = User.all; nil
  User Load (1.6ms)  SELECT "users".* FROM "users"
=> nil

[22] pry(main)> y User.first
  User Load (1.0ms)  SELECT "users".* FROM "users" LIMIT 1
--- !ruby/ActiveRecord:User
attributes:
  name: ghealey
  encrypted_password: $2a$10$rhYT.gbYbOanyudJa19cluQ1XlFFh4ntC8IhH5p.xxa9ddrtSx4.O
  created_at: 2010-11-26 05:51:01.32897
  failed_attempts: "0"
  updated_at: 2012-11-14 06:20:53.496916
  last_sign_in_ip:
  email: ghealey@example.com
=> nil


References:
http://37signals.com/svn/posts/3176-three-quick-rails-console-tips
http://samuelmullen.com/2012/07/getting-more-out-of-the-rails-console/
http://paulsturgess.co.uk/articles/39-debugging-tips-in-ruby-on-rails
http://www.therailworld.com/posts/35-Interacting-with-Controllers-via-the-app-object



Tuesday, November 13, 2012

Jenkins, Rails - Run rails test directly on Jenkins workspace

$ cd /var/lib/jenkins/jobs/[Jenkins_project_name]/workspace/
$ RAILS_ENV=test bundle exec rake test:units

Rails - Trace and solve rake db migration error

    We were doing a simple db migration in which a new column, say 'valuation_date', is added to an existing model 'Record'.  In the migration, the valuation_date column is added.  Then a code segment is executed to assign value to it.  Like this:

  def self.up
    add_column :records, :valuation_date, :date

    Record.find_each do |record|
      record.valuation_date = ...
      record.save
    end
  end


    The deployment (rake db:migrate) works fine on development environment.  However, when doing cap deploy:migrations, it returns error:

==  AddValutionDateToRecords: migrating ===================================
-- add_column(:records, :valuation_date, :date)
   -> 0.0014s
rake aborted!
An error has occurred, this and all later migrations canceled:

undefined method `column' for nil:NilClass

Tasks: TOP => db:migrate
(See full trace by running task with --trace)



    Turns out this only happens when running the migration under rails' staging environment.  Then tried execute the db migration and trace the issue.
$ bundle exec rake RAILS_ENV=staging db:migrate --trace

undefined method `relation' for nil:NilClass
/Users/laileo/.rvm/gems/ree-1.8.7-2011.03@merlot/gems/arel-2.0.10/lib/arel/crud.rb:12:in `update'
/Users/laileo/.rvm/gems/ree-1.8.7-2011.03@merlot/gems/activerecord-3.0.11/lib/active_record/persistence.rb:266:in `update'
/Users/laileo/.rvm/gems/ree-1.8.7-2011.03@merlot/gems/activerecord-3.0.11/lib/active_record/locking/optimistic.rb:77:in `update'
/Users/laileo/.rvm/gems/ree-1.8.7-2011.03@merlot/gems/activerecord-3.0.11/lib/active_record/attribute_methods/dirty.rb:68:in `update'
/Users/laileo/.rvm/gems/ree-1.8.7-2011.03@merlot/gems/activerecord-3.0.11/lib/active_record/timestamp.rb:60:in `update'
...

    To look deeper, set a "debugger" breakpoint before record.save.  Then another 2 breakpoints on crud.rb:12 .../active_record/base.rb:1718.  It was found that record.class.arel_table['valuation_date'] is nil that caused the failure.

Investigation #1
    Check if the Arel using different version in different environments.  In debug mode, $ p Arel::VERSION show they are the same.

Investigation #2
    Compare the difference between dev and staging:
$ rake about
$ rake RAILS_ENV=staging about

    The results show that ActionDispatch::Static middleware is not include in staging.  Tried to comment out the config.serve_static_asserts = false in config/environments/production.rb.  Then the middleware ActionDispatch::Static is added.  But it doesn't help.

Investigation #3
    Change the settings on config/environments/production.rb to those in config/environments/development.rb one by one to locate what makes the difference.  Luckily, the first one hits.  It is the config.cache_classes=true on staging environment that leaded to the error.  The model column was cached and not reloaded after add_column.  So, the assign and save of a record resulted in error.  To solve the problem, after add_column, do a reset_column_information.  i.e.

  def self.up
    add_column :records, :valuation_date, :date

    Record.reset_column_information

    Record.find_each do |record|
      record.valuation_date = ...
      record.save
    end
  end


Problem solved!

Friday, November 2, 2012

Rails note - Builds single purpose controller method/route

Just a simple note:

In Rails application, it would be better for every controller
method/route serves single purpose, instead of multiple purposes and
switch by parameter options.

This approach provides a cleaner view for system maintenance and auditing.

Monday, October 22, 2012

Right tools for the right task - Reasons for moving from Node.js to Ruby on Rails

reference:http://www.aqee.net/why-we-moved-from-nodejs-to-ror/

为什么我们要从 NodeJS 迁移到 Ruby on Rails



声明:这篇文章绝不是一篇讨论 NodeJS 和 Ruby on Rails 孰优孰略的檄文。它描述的只是我们做决策过程中的一些思考、决策背后的原因。两种框架都非常优秀,都出色的完成了它们的设计初衷,这也是为什么我们部分的 模块仍然运行在NodeJS上的原因。

我是NodeJs的大粉丝,认为这是一项让人非常兴奋的技术,相信它会变的越来越流行。我对这项技术非常的欣赏——尽管我们最近把Targeter App从NodeJS迁移到了Ruby on Rails。
我们当时使用NodeJS开发 它的原因很简单。我有一个程序包,能很快的将我们的应用弄上线(我们花了54小时做这个事情),相比起Ruby,我更常使用的是 JavaScript。因为我们的技术架构牵涉到MongoDB,我的这些特长只有在NodeJS环境里才会有意义。然而,随着应用规模的增 长,我认识到,选择NodeJS来实现这个应用是个错误的选择。下面让我来概述一下其中的原因。
NodeJS很适合做那些有大 量短生命期请求的应用。对于传统的CRUD应用,它也很好,但不是非常的理 想。在PHP,Ruby,Python语言里都有很成熟、优化的很好的框架来处理这种应用。NodeJS里的所有东西都异步执行的理念对于 CRUD应用来说没有任何效果。其它语言里的流行的框架能提供非常好的缓存技术,你所有的需求都能满足,包括异步执行。
NodeJS是一种非常年 轻的技术框架,它的周边程序库都不是很成熟。我说这些并没有任何对那些代码捐赠者冒犯的意思,他们很优秀,开发出来很 多优秀的程序库。然而,大部分程序库需要改进,而NodeJS的这种快速成长的环境意味着每一版升级中都带有大量的变化;当你使用一种前沿技 术时,你十分有必要尽快的紧跟最新的版本。这给创业型的企业带来了很多的麻烦。
另外一个原因是关于测 试。NodeJS里的测试框架还不错,但跟Django或RoR平台上的相比还是差一些。对于一个每天都有大量的代码 提交、并且在一两天内就要发布的应用来说,程序不能出问题是至关重要的,否则你为此辛苦的努力变得得不偿失。没有人愿意花一天的时间改一些弱 智的bug。
最后一点,我们需要的是一种能缓 存一切的东西,并且要尽快的实现。尽管我们的应用在增长,每秒钟有上万次的hits,但绝不会出现很大量的访问请求; 这不是一个聊天程序!主程序最多时也就达到1000RPS,这样的负载对于Ruby on Rails和Nginx来说算不了什么。
如果你现在还在读这篇文章,那 你已经看到了我所有要说的了,你也许非常坚持的想知道我们的应用什么地方还在使用NodeJS。是这样的,我们的应用由两部分组成。一是界 面,用户看到的这部分,二是负责报表管理的部分,以及做日志的功能。后者是NodeJS的一个最佳使用场景,存在有大量的短周期的请求。这部 分的动作需要尽快的执行完成,甚至要在我们的数据推送还没有完成之前。这很重要,当请求执行还未结束,浏览器继续等待响应结束,这会影响用户 使用体验。NodeJS的异步特性救了我们。数据要么被存入数据库,要么被处理掉,当请求一旦执行完成,浏览器就可以开始做其它重要的事情 了。

Wednesday, October 17, 2012

Rails - A note on lib files

Rails server needs to be restarted to reflect any code changes.

Tuesday, October 16, 2012

A behind-the-scenes look at LinkedIn’s mobile engineering

Reference: http://arstechnica.com/information-technology/2012/10/a-behind-the-scenes-look-at-linkedins-mobile-engineering/

LinkedIn is the career-oriented social network that prides itself on professional excellence. But the company's original mobile offering was anything but—it left much to be desired. There was an iPhone application, but no support for Android or tablets. The backend was a rickety Ruby on Rails contraption; afflicted with seemingly insurmountable scalability problems. And despite serving only seven or eight percent of the LinkedIn population, the company's original mobile build required approximately 30 servers in order to operate. This was clearly not made to sustain a growing mobile user base.
Now, a little over a year has passed since LinkedIn relaunched its mobile applications and website. And the company recently marked the anniversary by debuting a number of new mobile features, including real-time notifications and support for accessing company pages from mobile apps.
Mobile is gradually becoming a central part of the LinkedIn landscape. The company says roughly 23 percent of its users access the site through one of its mobile applications, up from ten percent last year. As our friends at Wired reported last month, the underlying design language and development philosophy behind the company's mobile experience is playing an influential role as the company works to revamp its website.
No one knows more about this paradigm shift than Kiran Prasad, LinkedIn's director of mobile engineering. Prasad was one of the key players in LinkedIn's efforts to resurrect its mobile offerings, and he was kind enough to walk Ars through the process. LinkedIn's mobile man provided a behind-the-scenes look at how the company built its mobile applications and the associated backend infrastructure, while also describing the design strategy the company used to build its mobile interfaces. As you'd probably expect from the brand, it was all a professional level effort.

Initiating an overhaul

LinkedIn decided it was time for a massive overhaul as the company began recognizing the increasingly important role that mobile access would play for the social network's users. Jet-setting professionals rely on their smartphones to stay in touch while they travel, right?
Mobile soon became a major strategic focus for LinkedIn. In August of 2011, roughly five months after the mobile overhaul began, the company launched an all-new set of mobile apps powered by a completely new backend.
When the effort began, the mobile engineers at LinkedIn had several major goals. They wanted cross-platform compatibility, with support at launch for Android, iOS, and the mobile Web. They also wanted to simplify the user interface, taking the number of icons on the main screen down from 12 to three or four. Finally, they wanted a holistic rewrite—rebuilding both the frontend and backend together with an eye for boosting scalability.
Prasad previously worked on WebOS at Palm before joining LinkedIn. He brought a wealth of knowledge about building native-like user interfaces with modern Web standards. He regards the mobile Web as a platform in its own right, one that LinkedIn had to support well alongside Android and iOS. So Prasad decided that making HTML5 a central part of the company's mobile strategy would make it easier to reach all of those environments.
HTML offers a useful way to reach more screens, but Prasad believes there are still many places where native user interfaces and native code are needed in order to deliver the best possible user experience. LinkedIn set out to use a hybrid model; blending the two to theoretically offer advantages of both.
This approach made it easier for a small team to support multiple platforms. And crucially, it allowed other LinkedIn developers outside of the mobile team to contribute to the effort using their existing skills.

Everything must be simple

Prasad told me that simplicity is at the heart of LinkedIn's mobile vision. The company's internal definition of simplicity, he said, holds that a good solution must be fast, easy, and reliable—in that specific order. Each of those characteristics is considered ten times more important than the next, making performance the chief concern. That philosophy motivated his team's decisions in almost every area, ranging from visual design to backend engineering.
The thing people value most, according to Prasad, is their time. When users encounter flaws in software, they tend to be more forgiving if the software is extremely fast. A crash is less disruptive, for example, if the application is quick to restart and offers a quick path back to where the user was.
Speed is also especially important for mobile experiences in his eyes, because smartphone users tend to have shorter sessions (often less than three minutes long). Users expect applications to deliver relevant information as quickly as possible.
Ease of use was his next major priority, and Prasad said LinkedIn measures this by counting the number of clicks that it takes for a user to complete a given operation. If it takes more than three, he said, users are going to lose patience and easily be drawn away by push notifications or other things happening on their phone.
Reliability is the final of the three priorities. Basic robustness and stability are important, Prasad told me, but reliability also encompasses other ideas like consistency and predictability. To him, a reliable application is one the user can depend on to behave the same way every time. When the user taps a button and it takes them to another screen, for example, going back and tapping on the same button should take them there again. A surprising number of applications ignore that seemingly obvious design principle, Prasad said.
During the design process, LinkedIn used a simple metaphor to encourage predictability and ease of use. The idea is that an application is like a house—there are rooms with specific functions, and there are corridors that connect those rooms in a practical way. When you are putting together a room, you don't fill it with an incongruous range of functions. You may end up with a living room, a bedroom, a kitchen, and a bathroom. But you don't cook in the living room and you don't sleep in the bathroom.
Continuing this house analogy, when you begin designing an application, you start by defining the structure. You determine what rooms you want, what their purposes will be, and how those rooms will be connected. You don't start with the visuals (in the house analogy, these are like the carpeting or the paintings on the walls). When you introduce a feature, you think about the room in which it belongs.
For the mobile application, LinkedIn decided that it didn't want more than four "rooms" of functionality. You can clearly see the house metaphor in action when you open the LinkedIn iPhone application. The main screen limits itself to four icons: your updates, profile, messages, and groups. It serves as the hallway, allowing the user to tap an item in order to enter a given room.

Building a hybrid app with HTML5 and native code

LinkedIn uses a combination of HTML5 and native code in its user interface. Prasad told me which technologies they use for various parts of the app and gave me a detailed explanation of how LinkedIn has made the two approaches interoperate.
Prasad says that HTML is very effective at rendering what he calls "detail" views, large blocks of informational content consisting largely of rich text and graphical media. The flexible layouts offered by HTML make it useful for such usage scenarios, but there are also major areas where LinkedIn chose to use native controls. Why? Prasad said Web technologies weren't entirely up to the task.
Prasad dismisses the idea that you have to choose between native controls and HTML, saying that it represents a false dichotomy. Ultimately, LinkedIn's iPhone application consists of 70 percent HTML and 30 percent native.
The biggest example he cited of an area where HTML5 still falls short as a user interface layer for data-driven mobile applications is in displaying long lists of content. He said that native widgets are needed in order to achieve smooth and seamless scrolling for list displays with hundreds or thousands of items. Attempting to display such lists with HTML and JavaScript proved impractical. Prasad saw this as especially true for "infinite" lists, where new content is fetched dynamically and appended to the bottom as the user scrolls.
When implementing an infinite list, you can't just keep adding items to the bottom. Memory overhead quickly becomes unacceptable unless you also simultaneously pull items from the top after the user has scrolled past. Prasad explained that manipulating the HTML DOM (Document Object Model) during scrolling caused some stuttering.
It's hard to measure exactly what is going on when that happens, but LinkedIn guessed that page layout computations or JavaScript garbage collection were sapping too much of the device's limited resources. On top of the performance issues, Prasad felt it was exceptionally difficult to implement kinetic scrolling in HTML that felt truly native across platforms.
It's worth noting that rival social network Facebook raised very similar concerns about list performance and scrolling in a recent message to a W3C mailing list. Facebook largely ended up swapping HTML for native user interface controls in the latest update of its own mobile application.
For Prasad, however, the limitations of current Web rendering engines don't demand a full return to native code—it's a matter of using the right tool for the job. He dismisses the idea that you have to choose between native controls and HTML, saying that it represents a false dichotomy.
Ultimately, LinkedIn's iPhone application consists of 70 percent HTML and 30 percent native. The Android application is roughly 40 percent native and 60 percent HTML. The Android application relies more extensively on native elements because the platform's HTML rendering engine isn't quite as capable as the one on iOS.
LinkedIn had started with an 80-percent-native Android application, but has been able to gradually increase the amount of HTML over time due to incremental improvements in the platform's HTML renderer. Prasad is hopeful that the greatly enhanced HTML renderer that comes with Chrome for Android will eventually be available in the embeddable HTML display component that Android supplies for third-party applications. He described Chrome for Android as "awesome" and said that its support for hardware-accelerated rendering is great.
Aside from handling some performance-critical user interface elements like lists, the native part of LinkedIn's application also serves a vital role in trapping and responding to errors uncovered in the embedded HTML views. In cases where an embedded HTML pane encounters a fatal error, the native part of the application can cleanly bring it down and then repopulate it, often without the user even knowing.
Prasad briefly discussed his views on Web runtime solutions, such as PhoneGap, that aim to simplify HTML-based mobile application development and provide such applications with native shims to underlying platform functionality. While PhoneGap and similar frameworks are useful for rapid prototyping and for companies with limited resources, he said, it's better to implement the native parts of hybrid mobile software in a way that meets the specific requirements of the individual application. Ideally, he told me, developers should choose the right balance between native and Web for each application and then build their own bridge between the two environments.
I asked him to describe the specific mechanism he uses on each platform to enable communication between native code and the HTML user interface elements. On Android, the LinkedIn application largely relies on the platform's built-in support for exposing specific Java functions into the JavaScript runtime of an embedded HTML view. That feature made it relatively straightforward to bridge the gap.
On iOS, the matter is a bit more complicated. He said the company tried several different methods before settling on one they felt was most effective. Their first approach involved using a platform API to "eval" JavaScript expressions in the embedded WebView. This proved to be too computationally expensive, sometimes introducing undesirable jerkiness.
The second approach that LinkedIn tested was one using WebSockets to establish a connection between the HTML components and native code. This worked exceptionally well from a performance perspective, but wasn't stable enough for practical use. LinkedIn used this method in an actual release, but later replaced it.
Finally LinkedIn tested, and ultimately chose to adopt, something surprising. The company embedded an extremely lightweight HTTP server in the application itself. The HTTP server exposes native functionality through a very simple REST API that can be consumed in the embedded HTML controls through standard JavaScript HTTP requests. Among other things, this server also provides access to the user's contacts, calendar, and other underlying platform functionality.
When I asked Prasad if this approach raised any security issues, he said that the company reviewed it internally and found it to be acceptable. There are a number of precautions that are taken in the application to prevent it from being abused. The server is bound only to localhost and can't be accessed by other devices on the network. It also suspended immediately whenever the LinkedIn application is sent to the background.
Building a more scalable backend
When LinkedIn was deciding how to rebuild its backend, the company used a similar philosophy to the one that had directed the application design decisions. Like everything else, they wanted their backend technology stack to be fast, easy to work with, and reliable.
In a large-scale backend system, Prasad said, companies typically adapt the traditional model-view-controller (MVC) pattern into a three-tier system. The bottom tier consists of the database storage layer, the middle tier handles caching and some business logic, and the top tier serves as the presentation layer, generating your HTML views.
When you are building a mobile application, he said, this structure is no longer applicable. Your presentation layer is on the device itself, often consisting of native user interface elements. LinkedIn wanted a new kind of middle tier that would facilitate more effective communication with a mobile frontend.
In order to minimize the latency introduced by establishing new connections, the LinkedIn developers decided the application should establish as few connections as possible with the server. This led them to a model where the application is essentially piping all of its data through a single connection that is held open for as long as it is needed.
The client application connects to a system on the backend that functions as an aggregator, pulling together all of the data that it needs from various components of the backend stack and combining it all into a unified stream of data that can be piped down to the client application through a single open connection.
To build this streamlined middle tier, the LinkedIn developers wanted to use a lightweight event-driven framework. They also wanted an environment that would be well-suited to handle the aggregation and string interpolation capabilities required for the service. They tested several candidates, including Ruby with EventMachine, Python with Twisted, and the JavaScript-based Node.js framework.
They found that Node.js, which is based on Google's V8 JavaScript engine, offered substantially better performance and lower memory overhead than the other options being considered. Prasad said that Node.js "blew away" the performance of the alternatives, running as much as 20 times faster in some scenarios.
Another advantage of adopting Node.js for the project is that it allowed LinkedIn's JavaScript engineers to put their existing expertise to use on the backend. Prasad said the company was able to combine its frontend and backend mobile teams into a single unit. The event-driven nature of frontend development made it easier for the user interface programmers to understand the way that Node.js works.
Prasad was practically giddy when he told me just how much the transition from Rails to Node.js improves the scalability of LinkedIn's mobile backend infrastructure. Impressively, the company was able to move from 30 servers down to three, while still having enough headroom to handle roughly ten times their current level of resource utilization.
Firefighting scalability problems on the old infrastructure had been a major distraction, one that forced the company's engineers to spend a lot of time just keeping the system running. With that problem defeated, the engineers were free to spend more time focusing on user-facing product improvements.

Perfection is elusive

The mobile engineers at LinkedIn have done some impressive work to make the application fast, responsive, easy to use, and aesthetically pleasing. But reliability, the third item in LinkedIn's taxonomy of mobile priorities, remains an issue for some users. LinkedIn's iOS application currently has an average rating of two-and-a-half stars out of five, with an average of three stars across all versions. The Android application fares a bit better, with 3.7 stars out of five. LinkedIn rolls out routine updates as it continues to improve its software.
LinkedIn's mobile application has also been the subject of privacy concerns. It faced scrutiny earlier this year when security researchers discovered that it was programmed to send user calendars back to the LinkedIn mothership. The company responded by tweaking this behavior and attempting to make it more transparent to the end-user.
But ultimately, building a mobile experience for a popular social network is not an easy task. Whatever shortcomings currently exist are being monitored, and could potentially be addressed in the same way this redesign built on past feedback. Prasad's description of the underlying technical details not only offers a glimpse into the challenges and complexity of this problem space, but he provides unique insight. When you experience LinkedIn mobile now, you're experiencing the company's engineering culture and the philosophy that guided its design and development process.

Sunday, October 14, 2012

Setup ctags on Mac for Rails development

The original ctags comes with Mac OS may say something like this when you run ctags -R:


$ctags -R
ctags: illegal option -- R
usage: ctags [-BFadtuwvx] [-f tagsfile] file ...

To solve the problem, install a new version and disable the original one:

$ brew install ctags
$ cd /usr/bin/
$ sudo mv ctags ctags.orig

Then $which ctags will give you the new installed ctags in /usr/local/bin/ctags.

Wednesday, October 10, 2012

Test email deliveries on Rails

In config/environments/test.rb, set "config.action_mailer.delivery_method = :test".  It tell action mailer not to deliver emails to the real world.  Instead, emails will be accumulates in the ActionMailer::Base.deliveries array.

So, in email test, do something like:

test "should send email" do
    assert_difference "ActionMailer::Base.deliveries.size" do
        ...
    end
    last_email = ActionMailer::Base.deliveries.last
    assert_equal, ..., last_email.from
    assert_equal, ..., last_email.subject
    ...
end

Rails initialization from yml configurations

Rails' startup initialization may read configurations from yml files.  For example, on development environment, developers may want exception notifications only be send to himself/herself.

So, developer may create a /config/config.yml (if not exists) for local development while commits a /config/config.yml.example for source control.  Then in config.yml, create a section like:

development:
    exception_email_recipient: someone@example.com


Next, in /config/initializers/exception_notification.rb, read the config from yml, like this:

filepath = "#{Rails.root.to_s}/config/config.yml"
local_config = YAML.load_file(filepath)
exception_email_to = local_config[Rails.env]['exception_notification_email_to']

Merlot::Application.config.middleware.use ExceptionNotifier,
    :email_prefix => "[Project_name][#{Socket.gethostname}] ",
    :sender_address => %{"Exception" <exception@example.com>},
    :exception_recipients => [ exception_email_to || 'production_recipient@example.com' ]


In this way, on exception emails goes to 'someone@example.com' on development platform.  While on production, it will goes to 'production_recipient@example.com'.

Tuesday, October 9, 2012

Rails - Lightweight smtp setting using sendgrid

Create an account on http://sendgrid.com/.

Add action_mailer setting in config file:

  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {:address => 'smtp.sendgrid.net', :user_name => '[account_name]', :password => '[password]'}

Keyword: rails, email, server