- 浏览: 861528 次
- 性别:
- 来自: lanzhou
-
文章分类
最新评论
-
liu346435400:
楼主讲了实话啊,中国程序员的现状,也是只见中国程序员拼死拼活的 ...
中国的程序员为什么这么辛苦 -
qw8226718:
国内ASP.NET下功能比较完善,优化比较好的Spacebui ...
国内外开源sns源码大全 -
dotjar:
敢问兰州的大哥,Prism 现在在12.04LTS上可用么?我 ...
最佳 Ubuntu 下 WebQQ 聊天体验 -
coralsea:
兄弟,卫星通信不是这么简单的,单向接收卫星广播信号不需要太大的 ...
Google 上网 -
txin0814:
我成功安装chrome frame后 在IE地址栏前加上cf: ...
IE中使用Google Chrome Frame运行HTML 5
Rails is a framework about conventions. It generates a basic structure which you mold into your dream application. Over the course of the years, we have gathered some basic, rails specific, hints and tips you might want to check before going live. They are split into sections to make it easier to scan them, and pick the ones you haven’t indulged (yet) in. Read on, have fun, and comment a lot…
ActiveRecord
ActiveRecord’s (AR) magic can be somewhat exciting for the newcomer. But there are some pitfalls to consider:
Don’t forget to :select
AR is RoR’s backbone. If you for example wanted to render all users whose username begins with the letter ‘A’ you would do:
1 @users = User.find(:all, 2 :conditions => ["username like ?", "A%"])
In fact most of the time you don’t actually need what the above command returns. It executes a select *
on the user table returning a carload of data, which leads to memory and cpu bloat. What you usually want to show is a small set of the User model attributes.
Using :select => [list of attribute names for your view]
you’ll reduce database traffic, keep AR happy and slim, and those mongrels to a minimum of your available system memory:
1 @users = User.find(:all, 2 :select => "username, email, registered_on", 3 :conditions => ["username like ?", "A%"])
Eager Loading? Yes, but…
One of the basic performance tips in every rails book/class/blog is to use :include => AssociationName
. By not using it, the following code:
1 <% for post in @posts %> 2 <!-- ........ --> 3 <%=h post.user.username %> <!-- user association requires one query --> 4 <% end %>
will result in extra queries one for each loop execution. Using eager loading, you can avoid excessive queries:
1 def index 2 @posts = Post.find(:all, :order => "posted_on desc", :limit => 15, :include => [:user]) 3 end
Now the user table is joined and we are all happy.
Rails is a convention framework and a pretty smart one too. Rails 2.0 added a caching mechanism to cache queries for the same action in case you (of course by devilish mistake) execute the same query more then once. But that’s just a countermeasure, you should make sure that your queries are properly joined.
Τhere was a but here, wasn’t it? I can hear you screaming that AR is now including all of the users data, even columns you don’t need. And you probably think that you’ll just have to use :select
to avoid it.
ActiveRecord completely ignores the select directive if you use include. Ouch!
There are two ways to work around this issue
- use select_with_include, a plugin that lets you
:select
together with:include
- use
:join
, instead of include
select_with_include
First you have to install the gem
1 > gem install select_with_include
Then you must require the gem in your environment.rb
1 require 'select_with_include'
Now, you can use the :select option
, remembering to use the table name even if a column name is not ambigious.
1 def index 2 @posts = Post.find(:all, 3 :select => "posts.title, posts.created_on, posts.comments_count, users.username", 4 :order => "posted_on desc", 5 :limit => 15, 6 :include => [:user]) 7 end
Select_with_include doesn’t support table selects (e.g. users.*
) and calculated fields. If you want to include all columns of a table, you’ll have to type each and every one of them.
I don’t know if select_with_include has any implications on performance. It’s a syntax parser so that should add some overhead but haven’t found any sources that actually prove it.
Using :joins, instead of :include
AR’s find method provides an option to manually specify join tables, using :joins
. In that case AR will not try to create objects for you, it will just append the join directive on the sql output and the :select
option will not be ignored. The following code snippets will show you what happens in each case:
1 @posts = Post.find(:all, 2 :select => "posts.id, posts.title, posts.subject, users.username", :include => :user)
Will generate the following sql command:
1 SELECT `posts`.`id` AS t0_r0, 2 `posts`.`title` AS t0_r1, 3 `posts`.`subject` AS t0_r2, 4 `posts`.`user_id` AS t0_r3, 5 ... 6 `users`.`username` AS t1_r1, `users`. 7 .... 8 LEFT OUTER JOIN `users` ON `users`.id = `posts`.user_id
As you can see, the :select
option was ignored by AR. We can use :joins
instead:
1 @posts = Post.find(:all, 2 :select => "posts.id, posts.title, posts.subject, users.username", 3 :joins => "left outer join users on users.id = posts.user_id")
that results to an sql query you can actually read:
1 SELECT 2 posts.id, 3 posts.title, 4 posts.subject, 5 users.username 6 FROM `posts` 7 LEFT OUTER JOIN users on users.id = posts.user_id
Note that you have to access the user’s attribute from within the post object and not from the association. That means to access the user name you should use @posts.first.username and not @posts.first.user.username. The latter will execute a new query to fetch the result.
In 99% of the cases that kind of hacking is unnecessary. You should identify parts in your application that need optimizing and apply whatever can make your app go faster.
Save without validations
A typical update or create action will end up with the model being saved by calling AR’s object.save
. Depending on the validation chain results, save
will return true or false and we’ll take the appropriate actions to handle that. Something like this:
1 def some_action 2 .... 3 if @post.save 4 end
When calling save
any validations defined in the model are validated in the background (some validations can also mean extra database queries). But what if we are updating the views_count of a blog post? We don’t want to add extra load to the database for no reason.
You can call object.save_with_validation(false)
to skip validations when doing trivial updates that require no validations. You can also use AR’s update
class if you don’t have the object in scope.
One more thing to consider. In a perfect world , your model instances should always validate. But there are cases where that will not happen. You added a new validation, someone changed something directly in the database, shit happens.
If you are updating a very important attribute (like someone’s purchased credits) avoid calling object.save
. You don’t want a user complaining about missing credits he paid for just because his email didn’t have the right format.
Going live
There are some nice little tools in the Rails world which make you wonder how you ever deployed an application without them.
Exception Notifier
First off this nifty little plugin. If you are not using it by now, start using it. It mails you a stack trace for every exception that occurs.
Set it up wisely, use ExceptionNotifier.email_prefix
with a unique prefix for every application, and filter those mails in your email client.
Asset packager
Rails as most of the other Web 2.0 frameworks comes bundled with a plethora of js files, most of us really never trim down to the very necessary. In order to minimize traffic for the js files you can use the asset packager.
Asset packager has to rebundle the js files each time you make changes. Make sure you set up a nice rake task to automate this.
Rendering the cool way
Partials and layouts in Rails can make your life easy. Nevertheless, some of the defaults that we are used to when coding the rails way, can cause problems if someone doesn’t pay any attention to them.
Move js to the bottom
It is important to have the process in mind a browser goes through when rendering your page.
First of all the HTML file is downloaded. Then the browser beginns top to bottom, to parse the HTML and execute if necessary extra calls as they are encountered.
We usually include our javascript files at the top of the layout. That means that browsers will try to download the javascript files before even having the DOM in place. As a result the actual content of the application will come delayed just because the browser was occupied opening connections and downloading files that we are not going to use only until after the markup code is fetched.
Moving your javascripts to the bottom will save you some loading time, especially for the newcomer that will not have the files cached.
DNS lookups for js files should be avoided. If the file doesn’t change download it once and serve it from your server.
If you are using rails javascript helpers like autocomplete, which are called before everything is dowloaded, you can still make them work using a simple trick. We’ve blogged about it before, so you can read everyting about it here
Watch your form’s attributes
So you code your form using the form helpers, and then pass the parameters to the newly created or to be updated object and save. Let’s say we have this user object with username, email, and purchased_credits and we’re designing a form for the user to change his email.
1 2 <% form_for :user, @user, :url => {:controller => "users", :action => "update_email", :id => @user.id} do |f| -%> 3 <p> 4 <label for="user_email">Email: </label> <%= f.text_field :email %> 5 </p> 6 <p> 7 <%= submit_tag "Change" %> 8 </p> 9 <% end %> 10
Then inside the controller we update the user’s mail
1 def update_email 2 #all access and db logic handled with before filters 3 if @user.update_attributes(params[:user]) 4 flash[:notice] = "We did it" 5 else 6 flash[:alert] = "Nope. We didn't make it" 7 end 8 end
When you are doing bulk updates like User.new(params[:user])
or user.update_attributes(params[:user])
you open the door to anyone updating important attributes that you only have (or should) have access to. In the above example someone can append user[:purchased_credits] = 1000
and make himself a gift.
What’s most important in this case is to always have this pitfall in mind when you are coding forms. The solution may vary depending on your business logic, but there is an elegant way of securing your “for your eyes only” attributes with attr_accessible
or attr_protected
.
Always secure your model’s important attributes from bulk updates using attr_accessible
or @attr_protected* in the model declaration. And write tests about it. Always!
1 class User << ActiveRecord::Base 2 3 attr_accessible :username, :email 4 #or 5 attr_protected :purchased_credits 6 #check rails documentation for more info 7 ....... 8 end
There are some more tips, most of them have to do with “application testing” and it wouldn’t be fair to squeeze them in one post. Stay tuned for part 2.
发表评论
-
Rails 3 Beta版本月将出 Merb融合带来选择
2010-01-11 09:48 1438Rails 3,目前流行Web开发框架Rails的一个升级版 ... -
MerbAdmin:Merb数据管理好帮手
2010-01-11 09:43 922Merb中要加入类似Django的Admin功能早有传闻,如今 ... -
rails cms
2009-12-28 20:29 1691Rails CMS alternatives ======= ... -
Generating Thousands of PDFs on EC2 with Ruby
2009-12-24 18:01 1083The Problem For about two mont ... -
Shrink your JavaScript with the Google Compiler Rails Plugin
2009-11-16 11:27 956Like it or not, JavaScript has ... -
Thank you, Rails
2009-11-06 18:21 583It’s fashionable, or perhaps in ... -
Top 50 Ruby on Rails Websites
2009-10-31 15:18 961We’re big fans of Ruby on Rails ... -
Let a human test your app, not (just) unit tests
2009-10-31 09:26 891I’m a big believer in unit test ... -
Heroku Gets Add-Ons: Serious Ruby Webapp Hosting Made Easy
2009-10-30 07:37 932Heroku is a Ruby webapp hosti ... -
Rails + Google Analytics = easy goal tracking
2009-10-29 20:38 914Google Analytics is an indis ... -
Integrating Flickr into your rails website
2009-10-29 20:37 1092In this post I’m going to show ... -
Ruby on Rails Roadshow in Austin Thursday
2009-10-29 14:25 823Justin Britten founded Prefine ... -
Ruby on Rails and the importance of being stupid
2009-10-21 08:13 831A tale of two servers… Server ... -
How a 1-Engineer Rails Site Scaled to 10 Million Requests Per Day
2009-10-20 14:49 794Ravelry is an online knitting ... -
Installing Rails on CentOS 5
2009-10-20 14:24 1220Note: Since this post origina ... -
CentOS配置lighttpd和rails
2009-10-20 14:22 1145lighttpd版本:1.4.18 fastcgi版本: ... -
Cells:将组件开发带入Ruby2.3
2009-10-20 09:17 1142cells "将使得面向组 ... -
High Quality Ruby on Rails Example Applications
2009-10-15 16:34 1484Sometimes to best way to get ... -
Install Passenger on Ubuntu
2009-10-07 10:17 825Phusion Passenger is one of the ... -
Installing Ruby on Rails with Apache on Ubuntu 9.04 (Jaunty)
2009-10-07 10:00 1042Installing Passenger and Depe ...
相关推荐
附上Jamis的rdoc模板文件,tar解压即可。 博文链接:https://lgn21st.iteye.com/blog/199681
9. **部署与运维**: 项目部署通常选择Heroku、AWS、DigitalOcean等平台,使用Git进行版本控制,通过Capistrano等工具自动化部署。监控和日志管理也很重要,如使用New Relic、Lograge等工具。 10. **测试**: ...
《Rails101_by_rails4.0》是一本专注于Rails 4.0.0版本和Ruby 2.0.0版本的自学教程书籍,它定位于中文读者,旨在成为学习Rails框架的参考教材。Rails(Ruby on Rails)是一个采用Ruby语言编写的开源Web应用框架,它...
Rails 3.1 和 Cucumber-Rails 1.2.0 是两个在Web开发领域非常重要的工具,尤其对于Ruby on Rails框架的测试和自动化流程。本文将深入探讨这两个组件,以及它们如何协同工作来增强软件开发的效率和质量。 首先,...
9. **ActiveJob**:Rails的后台任务处理框架,可以配合各种队列服务(如Resque、Sidekiq等)处理异步任务。 10. **Rails Console**:提供了一个交互式的命令行工具,用于检查和调试应用,执行Ruby代码,以及与...
标题 "Rails" 指的是 Ruby on Rails,一个开源的Web应用程序框架,它基于Ruby编程语言,遵循MVC(模型-视图-控制器)架构模式。Rails由David Heinemeier Hansson在2004年创建,其设计理念是强调代码的简洁性、DRY...
在开发Web应用时,Ruby on Rails(简称Rails)框架因其高效、简洁的代码风格和强大的社区支持而备受青睐。Aptana是一款强大的集成开发环境(IDE),尤其适用于Rails项目的开发,它提供了丰富的特性来提升开发效率。...
### Ruby on Rails Guides v2 - Ruby on Rails 4.2.5 #### 一、重要概念及基础假设 - **重要概念**:本指南旨在帮助读者深入理解Ruby on Rails(以下简称Rails)4.2.5版本的核心功能与最佳实践。 - **基础假设**:...
本书《Component-Based Rails Applications》主要介绍了如何使用Rails引擎(Rails Engine)进行基于组件的Rails应用开发,以及如何对应用程序的大型模块进行拆分和模块化。以下是书中一些核心知识点的详细说明: 1....
9. **测试驱动开发(TDD)和集成测试**:Rails鼓励开发者使用Test::Unit或Rspec进行测试,确保代码质量。 10. **Rails发电机(Generators)**:自动化生成常见的代码结构,如模型、控制器、迁移等,提高开发效率。 ...
rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails ...
9. **tmp**:临时文件存储,如缓存、session等。 10. **vendor**:第三方库和依赖项的存放位置。 在购物系统(shopping_system)这个项目中,你可能会遇到以下概念和技术: - **ActiveRecord**:Rails内置的ORM...
Rails Recipes是一本针对Ruby on Rails框架的实用书籍,它收集了一系列高效解决问题的技巧和方法,也被称为“Rails开发者的宝典”。作者们通过分享自己的经验和见解,为Rails程序员提供了一本既有实际操作指导又有...
标题 "rails2.3.2" 指的是 Ruby on Rails 框架的一个特定版本,即 2.3.2。Ruby on Rails(通常简称为 Rails)是一个基于 Ruby 语言的开源 Web 应用程序框架,它遵循 Model-View-Controller (MVC) 设计模式,用于构建...
描述中提到,这是一个完整的Rails 2.3.8开发环境包,其中包括了Ruby 1.8.7,Rails 2.3.8,以及9个相关的Gem包。Gem是Ruby的包管理器,用于安装、管理和更新Ruby库。这些Gem包含了Rails框架的核心组件和其他依赖库,...
[Pragmatic Bookshelf] Crafting Rails Applications Expert Practices for Everyday Rails Development (E-Book) ☆ 图书概要:☆ Rails 3 is a huge step forward. You can now easily extend the framework, ...
9. **测试驱动开发(TDD)**:Rails鼓励采用TDD,提供了测试框架如RSpec和MiniTest,确保代码质量。 10. **Gem包管理**:Ruby的Gem系统使得安装和管理第三方库变得简单,如Devise用于用户认证,Paperclip或...