Francis's Octopress Blog

A blogging framework for hackers.

Getting Started With Rails-(EN-CN)

Getting Started with Rails-(EN-CN)

Getting Started with Rails

This guide covers getting up and running with Ruby on Rails. After reading it, you should be familiar with:本指导手册覆盖了入门和运行ruby on rails,通过阅读本指导,你会了解到:

  • Installing Rails, creating a new Rails application, and connecting your application to a database
  • The general layout#布局of a Rails application 应用程序的一般布局
  • The basic principles of MVC (Model, View Controller) and RESTful design MVC的基本原则和RESTful设计(理念)
  • How to quickly generate the starting pieces of a Rails application 如何快捷的开始一个Rails应用

ThisGuideisbasedonRails3.1.SomeofthecodeshownherewillnotworkinearlierversionsofRails.这个指导手册适用与Rails3.1,有些代码在Rails早期版本可能会不工作。

1 Guide Assumptions假设

1 Guide Assumptions

This guide is designed for beginners who want to get started with a Rails application from scratch#刻痕. It does not assume#假设that you have any prior#预先experience with Rails. However, to get the most out of it, you need to have some prerequisites installed:本指导设计给那些想大概的了解Rails应用创建的初学者。这里假设你对Rails没有任何预先的了解。不管怎样要得到(本手册的)知识,你需要预先安装:

  • The Ruby language version 1.8.7 or higher

Note that Ruby 1.8.7 p248 and p249 have marshaling#封送处理bugs that crash#意外崩溃紧急Rails 3.0. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02 though. Ruby 1.8.7 p248 and p249发行版1.8.7-2010.02 已经得到解决。On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults on Rails 3.0, so if you want to use Rails 3 with 1.9.x jump on 1.9.2 for smooth sailing.

Rails is a web application framework running on the Ruby programming language. If you have no prior experience with Ruby, you will find a very steep#learning curve diving straight into Rails. There are some good free resources on the internet for learning Ruby, including: Rails是一个基于Ruby程序语言的web程序框架。如果你没有预先的学习ruby,你会发现直接的入门Rails学习很有跨度。这里有一些学习ruby的免费互联网资源。

2 What is Rails?什么Rails

Rails is a web application development framework written in the Ruby language. It is designed to make programming web applications easier by making assumptions#完成about what every developer needs to get started. It allows you to write less code while accomplishing more than many other languages and frameworks. Experienced#经验丰富的Rails developers also report that it makes web application development more fun.Rails是一个使用Ruby语言编写的的web框架应用程序。其设计目的是为了让每个着手开始编写web应用程序的开发人员更加容易的完成工作。它允许你写最少的代码完成超过其他任何语言和框架所完成的工作。经验丰富的Rails开发人员还告诉我们通过Rails使设计web应用程序更快乐。

Rails is opinionated#自以为是software. It makes the assumption that there is a “best” way to do things, and it’s designed to encourage#鼓励that way – and in some cases to discourage alternatives替代品. If you learn “The Rails Way” you’ll probably discover a tremendous increase in productivity. If you persist in bringing old habits#习惯from other languages to your Rails development, and trying to use patterns模式you learned elsewhere, you may have a less happy experience.Rails是一个自以为是的软件。它使得我们以最好的方式去做事情,它还鼓励——and in some cases to discourage alternatives,如果你学习Rails方式你将会适时的发现生产力的巨大增长。如果你固守在来自其他语言的旧的习惯去进行你的Rails开发,以以它地方学来的模式尝试Rails,那么你将会得到很少的快乐的经历。

The Rails philosophy理念includes several guiding principles:Rails理念包含几个指导原则

  • DRY – “Dont Repeat Yourself – suggests that writing the same code over and over again is a bad thing. 不要自己重复——建议一次又一次编写同样的代码是一件坏事请。
  • Convention#约定Over Configuration(约定优于配置) – means that Rails makes assumptions about what you want to do and how you’re going to do it想做怎么做, rather than requiring you to specify every little thing through endless configuration files. 约定优于配置——意思是Rails对于你想做什么以及你想怎么做,你刻意的做很少的事情比编写无尽的配置文件更好
  • REST is the best pattern模式for web applications – organizing your application around resources#资源and standard HTTP verbs#动词is the fastest way to go. REST是开发web应用程序的最好模式——环绕resources和标准的HTTP动作组织你的应用程序

2.1 The MVC Architecture#MVC架构

At the core of Rails is the Model, View, Controller architecture, usually just called MVC. MVC benefits include:ModelViewController架构是Rails的核心,通常称之为MVC

  • Isolation分离of business logic逻辑from the user interface 界面#从用户界面的业务逻辑的分离
  • Ease of keeping code DRY# Dont Repeat Yourself
  • Making it clear where different types of code belong for easier maintenance #维护明确代码的不同之处使之跟容易维护
2.1.1 Models

A model represents代表the information (data) of the application and the rules to manipulate that data.模型代表了应用程序的信息(数据)和操纵这些数据的规则。In the case of Rails, models are primarily used for managing the rules of interaction with a corresponding#相应的database table. In most cases, each table in your database will correspond to one model in your application. The bulk of your application’s business logic will be concentrated in the models.Rails中,models主要用于管理数据表和相应的规则的互动。在大多数情况,在你数据库中的每个表都会和你的应用程序互动。你应用程序的逻辑业务将会集中放置在models中。

2.1.2 Views

Views represent the user interface of your application. In Rails, views are often HTML files with embedded Ruby code that perform执行tasks related solely to the presentation#演示of the data. Views handle the job of providing data to the web browser or other tool that is used to make requests from your application.View代表了应用程序的用户界面。在Rails中,Views通常是嵌入了执行演示数据任务的Ruby代码的HTML文件。Views完成了给web浏览器或者其他工具用于提出来自你的程序的请求提供数据。

2.1.3 Controllers

Controllers provide the “glue” between models and views. In Rails, controllers are responsible for processing the incoming requests from the web browser, interrogating the models for data, and passing that data on to the views for presentation.Controllers提供了models和视图间的粘合。在Rails中,controllers相应来自web浏览器请求的进程,向models询问数据以及传递数据给views用于演示。

2.2 The Components of Rails Rials的组件

Rails ships as many individual components.Rails关联着许多独立的组件。Each of these components are briefly explained below. 对这些组建在下面给出简要的解释。If you are new to Rails, as you read this section, don’t get hung up on the details of each component, as they will be explained in further detail later. 如果你是Rails的新人,当你阅读到这个部分,不要抛弃任何一个组件的描述,而且他们还会做进一步解释。For instance, we will bring up Rack applications, but you don’t need to know anything about them to continue with this guide.例如,我们将会构造应用骨架,但是在这里,你不需要知道关于他们的更进一步的任何知识。

  • Action Pack动作行为组
    • Action Controller 行为控制
    • Action Dispatch 行为传输
    • Action View 行为视图
  • Action Mailer 行为信封
  • Active Model
  • Active Record
  • Active Resource
  • Active Support
  • Railties
2.2.1 Action Pack

Action Pack is a single gem that contains Action Controller, Action View and Action Dispatch. The “VC” part of “MVC”.Action Pack是一个单独的包它包含了Action Controller, Action View and Action Dispatch传输调度。是MVCVC部分

2.2.1.1 Action Controller

Action Controller is the component that manages the controllers in a Rails application.The Action Controller framework processes incoming requests to a Rails application, extracts parameters, and dispatches them to the intended action. Services provided by Action Controller include session management, template rendering, and redirect management. Action Controller是在Rails中管理控制的组件。The Action Controller框架进程收到Rails应用程序的请求,提取参数,以及调度他们到具有相应义务的动作。这些服务是由Action Controller包含了会话管理部分,模板渲染(翻译),重定向部分。

2.2.1.2 Action View

Action View manages the views of your Rails application. It can create both HTML and XML output by default. Action View manages rendering templates, including nested and partial templates, and includes built-in AJAX support. View templates are covered in more detail in another guide called LayoutsandRendering.Action View管理你的Rails应用程序的视图。它可以以创建HTMLXML作为默认输出。Action View管理模板渲染,包含嵌套和组装模板,还包含了内置的AJAX支持。

2.2.1.3 Action Dispatch

Action Dispatch handles routing of web requests and dispatches them as you want, either to your application or any other Rack application. Rack applications are a more advanced topic and are covered in a separate guide called RailsonRack.行为调度处理了你的和其他部分的应用程序的路由——这些web请求以及一些你所想要的调度,

2.2.2 Action Mailer

Action Mailer is a framework for building e-mail services. You can use Action Mailer to receive and process incoming email and send simple plain text or complex multipart emails based on flexible templates.Action Mailer是一个营造E-mail服务的框架。你可以使用Action Mailer去发送、接收emial以及发送一些简单的计划文本或者基于灵活模板的复杂的多重的电子邮件。

2.2.3 Active Model

Active Model provides a defined interface between the Action Pack gem services and Object Relationship Mapping gems such as Active Record. Active Model allows Rails to utilize other ORM frameworks in place of Active Record if your application needs this.Active Model提供了Action Pack gem服务和Object Relationship Mapping gems之间的接口定义,比如Active记录。Active Model允许RailsActive Record部分去采用其他ORM框架如果你的应用程序需要。

2.2.4 Active Record

Active Record is the base for the models in a Rails application. It provides database independence, basic CRUD functionality, advanced finding capabilities, and the ability to relate models to one another, among other services.Active Record是一个Rails应用程序的models根本。它提供独立的数据库,基于CRUD功能,先进(高级)的查找能力,和与另一个models关联的能力,几乎所有其他服务。

2.2.5 Active Resource

Active Resource provides a framework for managing the connection between business objects and RESTful web services. It implements a way to map web-based resources to local objects with CRUD semantics.Active Resource提供一个管理目标业务和RESTful web服务之间连接的框架。它实现了使用CRUD语义测绘web-base 资源到本地目标。

2.2.6 Active Support

Active Support is an extensive collection of utility classes and standard Ruby library extensions that are used in Rails, both by the core code and by your applications.Active Support是一个广泛收集实用工具类和标准的Ruby库的扩展,它们由的核心代码和您的应用程序(决定)。

2.2.7 Railties

Railties is the core Rails code that builds new Rails applications and glues the various frameworks and plugins together in any Rails application.Railties是在Rails代码中创建新Rails应用和在任何Rails应用中粘和各种插件在一起的核心。

2.3 REST

Rest stands for Representational State Transfer and is the foundation of the RESTful architecture.Rest作为具有代表性的状态传输是RESTful架构的基础。This is generally considered to be Roy Fielding’s doctoral thesis博士论文, ArchitecturalStylesandtheDesignofNetwork-basedSoftwareArchitectures. While you can read through the thesis, REST in terms of Rails boils down to two main principles:当你阅读这篇论文RESTRails归纳为主要亮点原则:

  • Using resource identifiers such as URLs to represent resources.使用资源标识符比如URLs去表现资源
  • Transferring representations of the state of that resource between system components.转移(传送)在系统组件之间代表资源的状态

For example, the following HTTP request:

DELETE /photos/17

would be understood to refer to a photo resource with the ID of 17, and to indicate a desired action – deleting that resource. (系统)将会明白参照ID14phone资源,注明删除该资源。REST is a natural style for the architecture of web applications, and Rails hooks into this shielding屏蔽you from many of the RESTful complexities and browser quirks.REST自然风格去架构web应用程序,通过组件这样的钩子,使你避免了许多复杂的RESTful和浏览器之间的差异。

If you’d like more details on REST as an architectural#架构风格style, these resources are more approachable平易近人than Fielding’s thesis:

3 Creating a New Rails Project

If you follow this guide, you’ll create a Rails project called blog, a (very) simple weblog.如果你跟随这个指导,你将会创建一个叫做blogRails项目——一个非常简单的网络博客。Before you can start building the application, you need to make sure that you have Rails itself installed.当你准备开始构建这个项目之前你需要确保Rails已经完全安装。

3.1 Installing Rails安装Rails

In most cases, the easiest way to install Rails is to take advantage of RubyGems:在大多数情况下,最安装Rails简单的方式是通过方便的RubyGems

Usually run this as the root user:

# gem install rails#一般这样安装的rails都是最新的release版本

If youre working on Windows, you can quickly install Ruby and Rails with RailsInstaller.如果你的工作环境是Windows,你可以通过Rails Installer快速的安装Rails

/////////////////////////////

###gem help commands

~ gem install rails&&sudo gem install rails

ERROR: Could not find a valid gem ‘rails’ (>= 0) in any repository

ERROR: While executing gem (Gem::RemoteFetcher::FetchError)

Errno::ETIMEDOUT: Connection timed out connect(2) (http://rubygems.org/latest_specs.4.8.gz)

经检查和GFW无关,是rubygemsDNS 调整问题

 

问题解决的最好方法方法

jhjguxin@jhjguxin-virtual-machine:~/blog$ gem update —system

 

ERROR: gem update —system is disabled on Debian, because it will overwrite the content of the rubygems Debian package, and might break your Debian system in subtle ways. The Debian-supported way to update rubygems is through apt-get, using Debian official repositories.

 

If you really know what you are doing, you can still update rubygems by setting the REALLY_GEM_UPDATE_SYSTEM environment variable, but please remember that this is completely unsupported by Debian.

jhjguxin@jhjguxin-virtual-machine:~/blog$ export REALLY_GEM_UPDATE_SYSTEM=1

 

jhjguxin@jhjguxin-virtual-machine:~/blog$ gem updatesystem

 

###正是gem出问题了结果直接用sudo apt-get install rails,悲剧了ubuntu现在还是用的rails2.3的包然后导致,后面有些命令无法执行

3.2 Creating the Blog Application

The best way to use this guide is to follow each step as it happens, no code or step needed to make this example application has been left out, so you can literally follow along step by step.学习(使用)本指导的最好方式是跟随这里描述的每一步,不写代码或者没有例子所需的步骤会使得这个例子被冷落,你可以根据文字描述的步骤一步接着一步的操作。If you need to see the completed code, you can download it from GettingStartedCode.如果你需要完整的代码你可以从这里下载GettingStartedCode

To begin, open a terminal, navigate to a folder where you have rights to create files, and type:开始,打开一个terminal,导航至一个你有权限创建文件的文件夹,并输入:

rails new blog#—skip-bundle] # Don’t run bundle install这样在国内就不会由于连不上gem即便上能够上也会很慢半天没反映

#请确保你的rials 版本是3.1 不然的话这只能用下面的了

TheguidesforRails2.3arestillavailableathttp://guides.rubyonrails.org/v2.3.11/.

jhjguxin@jhjguxin-virtual-machine:~$ rails new blog#这里建立的文件夹名称为new额估计是新版本发生了或者有些地方没弄通(ubuntu 11.10 Rails 2.3.14 ruby 1.8.7 (2011-06-30 patchlevel 352) [i686-linux]

jhjguxin@jhjguxin-virtual-machine:~$ rails blog

jhjguxin@jhjguxin-Aspire-4750:~$ sudo gem install json -v 1.6.1

Invalid gemspec in [/var/lib/gems/1.8/specifications/tilt-1.3.3.gemspec]: invalid date format in specification: “2011-08-25 00:00:00.000000000Z”

Invalid gemspec in [/var/lib/gems/1.8/specifications/json-1.6.1.gemspec]: invalid date format in specification: “2011-09-18 00:00:00.000000000Z”

Invalid gemspec in [/var/lib/gems/1.8/specifications/tilt-1.3.3.gemspec]: invalid date format in specification: “2011-08-25 00:00:00.000000000Z”

Invalid gemspec in [/var/lib/gems/1.8/specifications/json-1.6.1.gemspec]: invalid date format in specification: “2011-09-18 00:00:00.000000000Z”

出现这个问题的时候我是改s.date=%q{2011-09-18}

rails3.1中由于要创建bundler信息(Gemfile文件)会提示你安装sqlite3等数据库信息,估计也就是你应用程序所用到的一些必须的modules

这里用的是sqlite3做数据库,提示的是安装的是sqlite3.

sudoapt-getinstallsqlite3sqlite3-doclibsqlite3-ruby

还是ERROR:Failedtobuildgemnativeextension.的话

sudoapt-getinstalllibxslt1-devlibxml2-devlibxslt-rubylibxslt1.1libxsltc-java-gcjlibxslt-ruby

libxslt1-dbglibxsltc-javaibxslthl-javalibxslt-ruby1.8

sudoapt-getinstalllibsqlite3-rubylibsqlite3-dev

sudogeminstalltherubyracer

####对于本地安装的rails(就是爬不出去墙的)sudogeminstallsqlite3-1.3.4.gem

成功了!

Yourbundleiscomplete!Usebundle</em></span></span></code><code></code><code><span style="color: #000000;"><span style="font-size: small;"><em>show</em></span></span></code><code></code><code><span style="color: #000000;"><span style="font-size: small;"><em>[gemname]toseewhereabundledgemisinstalled.

This will create a Rails application called Blog in a directory called blog.这里将创建一个名叫BlogRails应用程序在名称为blog的目录中。

You can see all of the switches that the Rails application builder accepts by running rails new -h.你可以通过运行rails new -h,查看rails应用程序创建器的所有命令(开关)。

After you create the blog application, switch to its folder to continue work directly in that application:当你创建了这个blog程序,跳转到它所在的文件夹中(直接对这个程序编辑).

$cd blog

In any case, Rails will create a folder in your working directory called blog. 在任何情况下,Rails将会创建一个名为blog的文件夹在你的工作目录中。Open up that folder and explore its contents.打开这个文件夹浏览其中的内容。Most of the work in this tutorial will happen in the app/ folder, but heres a basic rundown#概述on the function of each folder that Rails creates in a new application by default:在这个体验中的大多数的工作都是在app/这个文件夹中完成的,这里对Rails创建的新应用中的每一个文件夹的功能做出了一个概述:

File/Folder Purpose#目的
Gemfile This file allows you to specify what gem dependencies are needed for your Rails application. See section on Bundler, below.这个文件让你可以(添加)你的Rails所需要的特殊的gem依赖关系。
README This is a brief instruction manual#手册for your application. You should edit this file to tell others what your application does, how to set it up, and so on.这是一个简单的说明手册。你需要编辑这个文件告诉其他人你的应用程序可以做什么,怎么安装等等。
Rakefile This file locates and loads tasks that can be run from the command line. The task definitions are defined throughout the components of Rails. Rather than changing Rakefile, you should add your own tasks by adding files to the lib/tasks directory of your application.这个文件定位和载入能够在命令行中运行的任务。这个应该是域吧(任务定义)贯穿整个Rials的组件定义。除了修改Rakefile,你还需要添加你自己的任务的文件到你的应用程序的lib/tasks目录。
app/ Contains the controllers, models, views and assets for your application. You’ll focus on this folder for the remainder of this guide.包含controllers, models, views和你应用程序的assets(资源),再接下面的手册中你主要的注意力应该放在这里。
config/ Configure your application’s runtime rules, routes, database, and more.配置你的应用程序的运行的规则,(url)路由,数据库和其他。
config.ru Rack configuration for Rack based servers used to start the application.基于Rack服务器使用这个应用程序的Rack配置
db/ Shows your current database schema, as well as the database migrations. You’ll learn about migrations shortly.显示你当前的数据表,同样也显示数据迁移。你将会简单的了解关于(数据)迁移。
doc/ In-depth documentation for your application.应用程序的(深入)全面的文档。
lib/ Extended modules for your application (not covered in this guide).应用程序用到的扩展库(本手册没有涉及)
log/ Application log files.应用程序的日志文件
public/ The only folder seen to the world as-is. Contains the static files and compiled assets.这是外部可见的唯一文件夹。包含静态文件和编译资源。
script/ Contains the rails script that starts your app and can contain other scripts you use to deploy#部署配置or run your application.包含运行你的apprails脚本,或者其他用来配置或运行你的应用程序的scripts
test/ Unit tests, fixtures, and other test apparatus. These are covered in TestingRailsApplications单元测试,fixtures,或者其他test工具。他们在TestingRailsApplications里面有完整的讲述。
tmp/ Temporary files模板文件
vendor/ A place for all third-party code. In a typical Rails application, this includes Ruby Gems, the Rails source code (if you install it into your project) and plugins containing additional prepackaged functionality.放置第三方代码的地方。在一个典型的Rails应用程序中,这里包含Ruby GemsRails源代码(如果你把Rails安装到你的项目中)还包含一些预先包装好的额外的插件

3.3 Configuring a Database配置数据库

Just about every Rails application will interact with a database.基本上每个Rails应用程序都会和一个数据库互动。The database to use is specified in a configuration file, config/database.yml.使用的数据库在config/database.yml的配置文件中指定的。If you open this file in a new Rails application, you’ll see a default database configuration using SQLite3. The file contains sections for three different environments in which Rails can run by default:如果你在一个新的Rails应用程序中打开这个文件,你将会看到一个默认的数据库配置使用的是SQLite3.这个文件包含Rails可以默认运行的三个不同的环境会话。

  • The development environment is used on your development computer as you interact manually with the application. 开发环境使用在开发计算机上,让你和你的应用程序手动交互
  • The test environment is used to run automated tests. 测试环境用于运行自动测试
  • The production environment is used when you deploy your application for the world to use.产品环境在你向外发布过后使用
3.3.1 Configuring an SQLite3 Database

Rails comes with built-in support for SQLite3, which is a lightweight serverless database application.Rails内置并支持SQLite3SQLite3是一个轻量级的数据库服务器。While a busy production environment may overload SQLite, it works well for development and testing.但是一个繁忙的产品环境可能会导致SQLite超载,SQLite3更适合在开发或测试中使用。Rails defaults to using an SQLite database when creating a new project, but you can always change it later.Rails在创建一个新项目的时候默认使用一个SQLite数据库,但是你可以在之后随时更改。

Here’s the section of the default configuration file (config/database.yml) with connection information for the development environment:这是在开发环境中配置连接信息的默认配置文件的节选:

development:

adapter: sqlite3

database: db/development.sqlite3

pool: 5

timeout: 5000

In this guide we are using an SQLite3 database for data storage, because it is a zero configuration database that just works. 在这个手册中使用一个SQLite3数据库存存储数据,因为它不需要我们再去配置就能工作。Rails also supports MySQL and PostgreSQL “out of the box”, and has plugins for many database systems.Rails同样支持MySQLPostgreSQL ,它还有许多支持其他数据库系统的插件If you are using a database in a production environment Rails most likely has an adapter for it.如果你在产品环境中使用数据库对Rails来说仅仅是添加一个适配器而已。

3.3.2 Configuring a MySQL Database配置一个MySQL数据库

If you choose to use MySQL instead of the shipped SQLite3 database, your config/database.yml will look a little different.如果你选择MySQL代替SQLite3数据库,你的配置文件会有一点不同。Here’s the development section:这是开发环境下(的配置):

development:

adapter: mysql2

encoding: utf8

database: blog_development

pool: 5

username: root

password:

socket: /tmp/mysql.sock

If your development computer’s MySQL installation includes a root user with an empty password, this configuration should work for you. 如果你的开发计算机中安装的MySQL包含一个root用户和空的密码,这个配置文件就可以工作。Otherwise, change the username and password in the development section as appropriate.否则,修改合适的开发环境中使用的用户名和密码。

3.3.3 Configuring a PostgreSQL Database配置一个PostgreSQL数据库

If you choose to use PostgreSQL, your config/database.yml will be customized to use PostgreSQL databases:

development:

adapter: postgresql

encoding: unicode

database: blog_development

pool: 5

username: blog

password:

3.3.4 Configuring an SQLite3 Database for JRuby Platform配置在JRuby平台中使用的SQLite3数据库

If you choose to use SQLite3 and using JRuby, your config/database.yml will look a little different. Here’s the development section:

development:

adapter: jdbcsqlite3

database: db/development.sqlite3

3.3.5 Configuring a MySQL Database for JRuby Platform配置在JRuby平台中使用的MySQL数据库

If you choose to use MySQL and using JRuby, your config/database.yml will look a little different. Here’s the development section:

development:

adapter: jdbcmysql

database: blog_development

username: root

password:

3.3.6 Configuring a PostgreSQL Database for JRuby Platform配置在JRuby平台中使用的PostgreSQL数据库

Finally if you choose to use PostgreSQL and using JRuby, your config/database.yml will look a little different. Here’s the development section:

development:

adapter: jdbcpostgresql

encoding: unicode

database: blog_development

username: blog

password:

Change the username and password in the development section as appropriate.修改在开发会话中使用的合适的用户名和密码

You don’t have to update the database configurations manually. 你不是必须手动的配置数据库If you look at the options of the application generator, you will see that one of the options is named database. 如果你查看应用程序产生器,你将会发现一个选项(-d, —database=name Preconfigure for selected database (options: mysql/oracle/postgresql/sqlite2/sqlite3/frontbase/ibm_db).

This option allows you to choose an adapter from a list of the most used relational databases. You can even run the generator repeatedly: cd .. && rails blog —database=mysqlWhen you confirm确认the overwriting of the config/database.yml file, your application will be configured for MySQL instead of SQLite.

3.4 Creating the Database创建数据库

Now that you have your database configured,it’s time to have Rails create an empty database for you. 现在你已经有了你的数据库配置文件了,是时候创建一个空的数据库了。You can do this by running a rake command:

$ rake db:create #确保你的系统中已经有一个JavaScript runtime.#可能还需要执行sudo geminstalltherubyracer&&sudo gem install execjs

jhjguxin@jhjguxin-virtual-machine:~/blog$ rake db:create

rake aborted!

Could not find a JavaScript runtime. See https://github.com/sstephenson/execjs for a list of available runtimes.

one way:

并且In your Gemfile

write this

gem 'execjs'

gem 'therubyracer'

and then run

bundle install

#ubuntu环境中安装sqlite3sudoapt-getinstalllibsqlite3-rubylibsqlite3-dev 也尝试过使用gem install sqlite3-ruby但是网上说是gem nds有问题安装ruby mysqlsudoapt-getinstalllibmysql-ruby

another way:

参照上面的网址:我找了一个ubuntu里面有的Node.js就可以不用那个therubyracer

jhjguxin@jhjguxin-virtual-machine:~/blog$ rake db:create

This will create your development and test SQLite3 databases inside the db/ folder.将会在db/文件夹中创建你的开发环境的数据库文件development.sqlite3

Rake is a general-purpose command-runner that Rails uses for many things. You can see the list of available rake commands in your application by running rake -T.Rake是一个通用的命令行可以帮助Rails用户完成很多事情。你可以通过运行rake -T 查看可用的rake命令

ruby script/server#或者script/server

4 Hello, Rails!

One of the traditional places to start with a new language is by getting some text up on screen quickly. To do this, you need to get your Rails application server running.传统的方式之一,开始使用一种新的(命令)语法并得到快速掠过的文字。要得到这样的结果你需要使你的Rails程序运行。

$ rails server #——-rails2.3.1 $ ruby script/server#

This will fire up an instance of the WEBrick web server by default (Rails can also use several other web servers). 这里默认将开启一个WEBrick服务器的的实例(Rails也可能使用一些其他的web服务器)。To see your application in action, open a browser window and navigate to http://localhost:3000. You should see Rails’ default information page:查看你的应用程序的行为,打开一个浏览器并且导航到127.0.0.03000你将会看到一个Rails默认的信息页面。

To stop the web server, hit Ctrl+C in the terminal window where it’s running. In development mode, Rails does not generally require you to stop the server; changes you make in files will be automatically picked up by the server.要终止web服务,在命令运行的终端中按下Ctrl+C。在开发环境模式中,Rails一般不需要你停止服务;你所做的更改将自动的编译进需要的文件中并且重启服务。

The “Welcome Aboard#page is the smoke test for a new Rails application: it makes sure that you have your software configured correctly enough to serve a page.这个欢迎界面体现了一个新的Rails应用程序创建成功(通过了Rails的自检)。You can also click on the About your applications environment link to see a summary of your application’s environment.你可以点击About your applications environment查看你的应用程序运行环境摘要信息。

4.2 Say “Hello”, Rails

To get Rails saying “Hello”, you need to create at minimum a controller and a view.要使Rails说出(显示)你好,你还需要创建一个最小的a controller and a viewFortunately, you can do that in a single command. Enter this command in your terminal:幸运的是,你可以完成这些通过一行命令。在终端中输入: rails generate controller home index ##rails2.3.1 script/generatecontrollerhomeindex##

If you get a command not found error when running this command, you need to explicitly pass Rails rails commands to Ruby: ruby \path\to\your\application\script\rails generate controller home index.如果你在输入这个命令的时候出现没有这个命令错误,你需要明确的使用ruby来执行Rails命令。这里就没有rails这个文件应该是rubyscript/generatecontrollerhomeindex

Rails will create several files for you, including app/views/home/index.html.erb. Rails将会为你创建一些文件,包含app/views/home/index.html.erbThis is the template that will be used to display the results of the index action (method) in the home controller.这个模板会用来显示在home controller中的index action (method)的结果。Open this file in your text editor and edit it to contain a single line of code:在文本编辑器中打开这个文件并输入:

<h1>Hello, Rails!</h1>

4.3 Setting the Application Home Page

Now that we have made the controller and view, we need to tell Rails when we want “Hello Rails” to show up. 现在我们已经创建了controller view,我们还需要告诉Rails我们想在什么时候显示出来。In our case, we want it to show up when we navigate to the root URL of our site, http://localhost:3000, instead of the “Welcome Aboard” smoke test.在本例中,我们想让它在我们导航至站点url根目录的时候替代Welcome Aboard”显示。

The first step to doing this is to delete the default page from your application:首先移除应用程序中的默认页面。

rm public/index.html

We need to do this as Rails will deliver#提供,传输any static file in the public directory in preference#偏好优先to any dynamic#动态content we generate from the controllers.我们必须这样做因为,Rails将会传送任何在public的静态文件优先于我们在controllers生成的动态(显示)内容。

Now, you have to tell Rails where your actual home page is located.Open the file config/routes.rb in your editor. This is your application’s routing file which holds entries in a special DSL (domain-specific language) that tells Rails how to connect incoming requests to controllers and actions. This file contains many sample routes on commented lines, and one of them actually shows you how to connect the root of your site to a specific controller and action. Find the line beginning with root :to, uncomment it and change it like the following:现在你还必须告诉Rails 你实际上的主页在哪里。在文本编辑器中打开config/routes.rb 。这是你应用程序的路由文件,它采用DSL语言囊括了告诉Rails怎样连接请求信息到controllers and actions.的所有条目。

这个文件包含许多简单的路由命令,其中一条实际上是用于告诉我们怎样连接你站点根目录到一个指定的controller and acti。找到以root :to开头的那一行,注释掉它改成如下内容:

Blog::Application.routes.draw do

 

get “home/index”

 

root :to => “home#index”

//////////////////this depend on rails 2.3.1/////////

Blog::Application.routes.draw do

 

#…

# You can have the root of your site routed with “root”

# just remember to delete public/index.html.

map.root :controller => “home”

or

map.root :controller => “home”,:action => ‘index’

##root :to => “home#index”

The root :to => “home#index” tells Rails to map the root action to the home controller’s index action.

ps-ef|grepwebrick

kill-9上面得到的id强制结束WEBrick服务

Now if you navigate to http://localhost:3000 in your browser, you’ll see Hello, Rails!.现在你在浏览器中导航至http://localhost:3000 ,你将会看到Hello, Rails!”.

For more information about routing, refer to RailsRoutingfromtheOutsideIn.更多的信息请参见RailsRoutingfromtheOutsideIn

5 Getting Up and Running Quickly with Scaffolding使用Scaffolding快速创建并运行

Rails scaffolding is a quick way to generate some of the major pieces of an application. Rails scaffolding是一个快速的方法产生应用程序的一些主要的部分。If you want to create the models, views, and controllers for a new resource in a single operation, scaffolding is the tool for the job.如果你想使用一种简单的操作为新资源创建models,viewscontrollersScaffolding是一个不错的工具。

6 Creating a Resource创建一个资源

In the case of the blog application, you can start by generating a scaffolded Post resource: this will represent#代表,表现表示a single blog posting. To do this, enter this command in your terminal:在本示例中的blog应用程序,你可以使用scaffolded产生post资源:它表现为一个简单的blog posting。要完成这些,在终端输入如下命令:

$ rails generate scaffold Post name:string title:string content:text

rails 2.3.1 script/generate scaffold Post name:string title:string content:text

The scaffold generator will build several files in your application, along with some folders, and edit config/routes.rb. Here’s a quick overview of what it creates:scaffold创建器将会在应用程序中的一些文件夹中生成一些文件,并且还会编辑config/routes.rb。下面这些产生的文件的大概说明:

File Purpose
db/migrate/20100207214725_create_posts.rb Migration to create the posts table in your database (your name will include a different timestamp)将创建的posts表单迁移到你的数据库(会在你的命名前面加上时间)
app/models/post.rb The Post model Post模型
test/fixtures/posts.yml Dummy posts for use in testing 模拟测试post
app/controllers/posts_controller.rb The Posts controller
app/views/posts/index.html.erb A view to display an index of all posts 显示所有post
app/views/posts/edit.html.erb A view to edit an existing post编辑post
app/views/posts/show.html.erb A view to display a single post显示一条post
app/views/posts/new.html.erb A view to create a new post创建post
app/views/posts/_form.html.erb A partial to control the overall look and feel of the form used in edit and new views一个用于控制编辑和创建新视图的整体视效表
app/helpers/posts_helper.rb Helper functions to be used from the post views使用post的帮助功能views
app/assets/stylesheets/scaffolds.css.scss Cascading style sheet#层叠样式to make the scaffolded views look better #css使scaffolded视图具有更好的效果
app/assets/stylesheets/posts.css.scss Cascading style sheet for the posts controller#post controllercss效果
app/assets/javascripts/posts.js.coffee CoffeeScript for the posts controller
test/unit/post_test.rb Unit testing harness#利用for the posts model post modelsUnit测试
test/functional/posts_controller_test.rb Functional testing harness for the posts controller post controller的功能测试
test/unit/helpers/posts_helper_test.rb Unit testing harness for the posts helper post helperUint 测试
config/routes.rb Edited to include routing information for posts 加入posts 路由信息

While scaffolding will get you up and running quickly, the code it generates is unlikely to be a perfect fit for your application.即便是scaffolding使你创建和运行非常快捷,但是产生的代码不可能完美的适合你的应用程序。Youll most probably want to customize the generated code.你大多数都需要定制产生的代码。Many experienced Rails developers avoid scaffolding entirely, preferring to write all or most of their source code from scratch. 很多有经验的Rails开发人员完全不使用scaffolding,宁愿从头编写全部的代码。Rails, however, makes it really simple to customize templates for generated models, controllers, views and other source files.Rails,无论如何,使得为生成的modelscontrollersviews或者其他代码编定制模板非常简单。Youll find more information in the CreatingandCustomizingRailsGenerators&Templates guide.你可以在CreatingandCustomizingRailsGenerators&Templates看到更多信息。

6.1 Running a Migration

One of the products of the rails generate scaffold command is a database migration. Migrations are Ruby classes that are designed to make it simple to create and modify database tables. Rails uses rake commands to run migrations, and it’s possible to undo a migration after it’s been applied to your database. Migration filenames include a timestamp to ensure that they’re processed#处理in the order that they were created.script/generate scaffold的一个产品就是数据迁移。Migrations是一个ruby类被设计用来使数据库表单的创建和修改变得简单。Rails使用rake命令来执行迁移,它还可以撤销已经应用的修改。Migration filenames include a timestamp确保了迁移能够完成。

If you look in the db/migrate/20100207214725_create_posts.rb file (remember, yours will have a slightly different name记住,你得到的可能会有略微不同), here’s what you’ll find:

class CreatePosts < ActiveRecord::Migration

def change

create_table :posts do |t|

t.string :name

t.string :title

t.text :content

 

t.timestamps

end

end

end

The above migration creates a method name change which will be called when you run this migration.整个migration创建了一个名叫change的方法,该方法在你运行这个migration的时候被调用。The action defined in that method is also reversible#可逆, which means Rails knows how to reverse the change made by this migration, in case you want to reverse it at later date.这个方法中定义的行为也是可逆的,那就是说Rails知道怎样逆向改变这个migration,如果你需要恢复到上一次数据。By default, when you run this migration it will creates a posts table with two string columns and a text column. 默认情况下,当你运行这个migration,他将会创建一个包含两个字符串列和一个text列的表单。It also creates two timestamp fields to track record creation and updating. More information about Rails migrations can be found in the RailsDatabaseMigrations guide.关于Rails migration的更多信息请阅读RailsDatabaseMigrations手册。

At this point, you can use a rake command to run the migration:这个时候,你可以使用rake命令运行migration了:

rake db:migrate

Rails will execute this migration command and tell you it created the Posts table.Rails将会执行这个migration命令并且通知你它创建了Post表单。

== CreatePosts: migrating ====================================================

create_table(:posts)

–> 0.0030s

== CreatePosts: migrated (0.0032s) ===========================================

Because youre working in the development environment by default, this command will apply to the database defined in the development section of your config/database.yml file. If you would like to execute migrations in other environment, for instance in production, you must explicitly pass it when invoking the command: rake db:migrate RAILS_ENV=production.由于你默认工作在开发环境中,这个命令将会应用于开发环境会话的数据库位于你的config/database.yml 中。如果你想执行migration在其他环境中,比如以产品(环境)为实例,你必须明确调用的通过命令行中执行:rake db:migrate RAILS_ENV=production

6.2 Adding a Link添加要给link(到blog

To hook the posts up to the home page you’ve already created, you can add a link to the home page.把你已经创建好的post挂到主页上,你可以通过添加一个link到主页。Open app/views/home/index.html.erb and modify it as follows:打开app/views/home/index.html.erb并且按照下面所示更改:

<h1>Hello, Rails!</h1>

<%= link_to “My Blog”, posts_path %>

The link_to method is one of Railsbuilt-in view helpers.这个链接方法是Railsview helpers 的内建方法之一It creates a hyperlink based on text to display and where to goin this case, to the path for posts.它创建一个基于文字的超级链接并显示到哪里,在这个实例中(跳转)到posts

6.3 Working with Posts in the Browser

Now you’re ready to start working with posts. To do that, navigate to http://localhost:3000 and then click the “My Blog” link:现在你已经准备好在posts中工作了。导航至http://localhost:3000,并且点击My Blog”链接。

This is the result of Rails rendering the index view of your posts.这就是Rails渲染你的posts视图的结果。There arent currently any posts in the database, but if you click the New Post link you can create one.在你点击New Post链接并创建一个新的post之前,数据库里面是没有任何post的。After that, youll find that you can edit posts, look at their details, or destroy them. 随后你可以编辑,查看详细内容,或者删除他们。All of the logic and HTML to handle this was built by the single rails generate scaffold command.post的所有的logicHTML都是通过rails generate scaffold 生成的。

In development mode (which is what youre working in by default), Rails reloads your application with every browser request, so theres no need to stop and restart the web server.在开发模式中(你的默认工作模式),Rails会在每个浏览器请求的时候重新载入你的应用程序,因此你不需要停止或者重启web服务。

Congratulations, youre riding the rails! Now its time to see how it all works.恭喜,你已经驯服了rails!现在是时候去看看它的所有工作了。

6.4 The Model

The model file, app/models/post.rb is about as simple as it can get:

class Post < ActiveRecord::Base

end

There isnt much to this filebut note that the Post class inherits from ActiveRecord::Base.这里有可能不一致——但是切记Post类继承于ActiveRecord::BaseActive Record supplies a great deal of functionality to your Rails models for free, including basic database CRUD (Create, Read, Update, Destroy) operations, data validation, as well as sophisticated#复杂search support and the ability to relate multiple models to one another. Active Record免费为你的models提供了强大的功能,包括基本数据库的CRUD(创建,读取,更新,删除)操作,数据验证,以及复杂的的查询与其它数据表单多关联的字段的支持能力。

6.5 Adding Some Validation添加一些验证

Rails includes methods to help you validate the data that you send to models. Rails包含一些帮助你验证发送到models的数据的方法。Open the app/models/post.rb file and edit it:打开app/models/post.rb并编辑:

class Post < ActiveRecord::Base

validates :name, :presence => true

validates :title, :presence => true,

:length => { :minimum => 5 }

end

These changes will ensure that all posts have a name and a title, and that the title is at least five characters long. 这些更改会确保所有的post都有一个nametitile并且title长度至少五个字符。Rails can validate a variety of各种,很多conditions#名词(字段)in a model, including the presence or uniqueness独特of columns, their format, and the existence of associated相关objects. Rails可以验证很多种字段,比如字段能否为空和独特性,字段的格式,以及字段的关联。

6.6 Using the Console

To see your validations in action, you can use the console.要想在action里面查看你的验证你可以使用consoleThe console is a command-line tool that lets you execute#执行运行Ruby code in the context of your application:console是一个可以让你在你的应用程序的上下文中执行Ruby代码的命令行工具:

$ rails console

The default console will make changes to your database.默认的console将会改变你的数据库。You can instead open a console that will roll back any changes you make by using rails console —sandbox.你可以通过运行rails consolesandbox or rails console -s,这样你可以回滚你的任何操作。

jhjguxin@jhjguxin-Aspire-4750:~/blog$ rails console -s

Loading development environment in sandbox (Rails 3.1.1)

Any modifications you make will be rolled back on exit

irb(main):001:0> p=Post.new(:content=>“A new post to test console”)

=> #<Post id: nil, name: nil, title: nil, content: “A new post to test console”, created_at: nil, updated_at: nil>

irb(main):002:0> p.save

(0.2ms) SAVEPOINT active_record_1

(0.1ms) ROLLBACK TO SAVEPOINT active_record_1

=> false

irb(main):003:0> p.errors

=> #<ActiveModel::Errors:0xb6765d48 @base=#<Post id: nil, name: nil, title: nil, content: “A new post to test console”, created_at: nil, updated_at: nil>, @messages=#<OrderedHash {:title=>[“is too short (minimum is 5 characters)”, “can’t be blank”], :name=>[“can’t be blank”]}>>

This code shows creating a new Post instance, attempting to save it and getting false for a return value (indicating that the save failed), and inspecting the errors of the post.这段代码演示了创建一个Post实例,并企图保存到数据库并得到一个失败的返回值(说明保存失败的原因),检查post的错误信息。

When you’re finished, type exit and hit return to exit the console.当你操作完成,输入exit并回车退出console

Unlike the development web server, the console does not automatically load your code afresh for each line.不像开发环境的web服务器console不会自动导入你每行输入的新的代码。If you make changes to your models while the console is open, type reload! at the console prompt to load them.如果你改变了你的moels并且console是打开的,输入reload!那么console会立即导入他们。

jhjguxin@jhjguxin-Aspire-4750:~/blog$ rails console

Loading development environment (Rails 3.1.1)

irb(main):001:0> p=Post.new(:title=>“test console”,:name=>“jhjguxin”,:content=>“A new post to test console”)

=> #<Post id: nil, name: “jhjguxin”, title: “test console”, content: “A new post to test console”, created_at: nil, updated_at: nil>

irb(main):002:0> p.save

SQL (13.4ms) INSERT INTO “posts” (“content”, “created_at”, “name”, “title”, “updated_at”) VALUES (?, ?, ?, ?, ?) [[“content”, “A new post to test console”], [“created_at”, Sat, 05 Nov 2011 15:55:17 UTC +00:00], [“name”, “jhjguxin”], [“title”, “test console”], [“updated_at”, Sat, 05 Nov 2011 15:55:17 UTC +00:00]]

=> true

irb(main):003:0> reload!

Reloading…

=> true

###如果是rails console —sandbox could not reload! Successfully.

6.7 Listing All Posts

The easiest place to start looking at functionality is with the code that lists all posts. 寻找所有功能的地方是使用代码列出所有的postOpen the file app/controllers/posts_controller.rb and look at the index action:打开文件app/controllers/posts_controller.rb,并且查看index action

def index

@posts = Post.all

 

respond_to do |format|

format.html # index.html.erb

format.json { render :json => @posts }

end

end

Post.all calls the Post model to return all of the posts currently in the database. Post.all调用Post model并返回当前在数据库中的所有postThe result of this call is an array of posts that we store in an instance variable called @posts.本次调用的结果是一个post的数组,并且我们将这个数组存储在一个叫做@posts的实例变量中。

For more information on finding records with Active Record, see ActiveRecordQueryInterface.查找有关Active Record更多的信息,可以查看ActiveRecordQueryInterface相关记录。

The respond_to block handles both HTML and JSON calls to this action.这个respond_to块处理了这个动作的HTMLJSON请求。If you browse to http://localhost:3000/posts.json, you’ll see a JSON containing all of the posts.如果你浏览http://localhost:3000/posts.json,你将会看到一个JSON包含着所有的postThe HTML format looks for a view in app/views/posts/ with a name that corresponds to the action name. 这个HTML格式在app/views/posts/view中查找相对应的动作名称。Rails makes all of the instance variables from the action available to the view.Rails使来自action的所有的实例变量对应到(可用)viewHere’s app/views/posts/index.html.erb:

<h1>Listing posts</h1>

 

<table>

<tr>

<th>Name</th>

<th>Title</th>

<th>Content</th>

<th></th>

<th></th>

<th></th>

</tr>

 

<% @posts.each do |post| %>

<tr>

<td><%= post.name %></td>

<td><%= post.title %></td>

<td><%= post.content %></td>

<td><%= link_to ‘Show’, post %></td>

<td><%= link_to ‘Edit’, edit_post_path(post) %></td>

<td><%= link_to ‘Destroy’, post, :confirm => ‘Are you sure?’, :method => :delete %></td>

</tr>

<% end %>

</table>

 

<br />

 

<%= link_to ‘New post’, new_post_path %>

This view iterates#迭代over the contents of the @posts array to display content and links.这个view迭代@posts数组所有的内容并显示相关的内容和链接。A few things to note in the view:关于视图note一些信息:

  • link_to builds a hyperlink to a particular destination link_to创建一个超链接到一个地方
  • edit_post_path and new_post_path are helpers that Rails provides as part of RESTful routing.edit_post_path and new_post_pathRails提供的RESTful路由向导。You’ll see a variety of these helpers for the different actions that the controller includes. 不同的具有controlleractions中你将会看到一系列的这样的向导。

In previous versions of Rails, you had to use <%=h post.name %> so that any HTML would be escaped before being inserted into the page.在以前的版本的Rails中,你必须使用<%=h post.name %> 以避免一些HTML可能会转义在插入到页面之前。In Rails 3.0, this is now the default.Rails 3.0,作为默认。To get unescaped HTML, you now use <%= raw post.name %>.得到一个非转义的HTML,你现在使用<%=raw post.name%>.

For more details on the rendering process, see LayoutsandRenderinginRails.了解更过关于渲染处理流程,阅读LayoutsandRenderinginRails.

6.8 Customizing the Layout定制布局

The view is only part of the story of how HTML is displayed in your web browser.view仅仅告诉HTML要显示什么(内容)在你的web浏览器里面。Rails also has the concept of layouts, which are containers for views.Rails也有关于布局的概念(定义),那就是(布局)是对viewi的包装。When Rails renders a view to the browser, it does so by putting the view’s HTML into a layout’s HTML.Rails渲染一个view到浏览器,它通常是(这样做)把viewHTML放进布局的HTML中。In previous versions of Rails, the rails generate scaffold command would automatically create a controller specific layout, like app/views/layouts/posts.html.erb, for the posts controller. 在以前的版本中,rails generate scaffold 命令将会自动创建controller对应指定的布局。However this has been changed in Rails 3.0. An application specific layout is used for all the controllers and can be found in app/views/layouts/application.html.erb. 然而在rails3.0中有所不同了。一个应用程序指定的布局适用于所有的controllers,可以在app/views/layouts/application.html.erb 中找到(这就好像是djangobase.html)Open this layout in your editor and modify the body tag:打开这个layout在你的编辑器中并且修改body标签:

<!DOCTYPE html>

<html>

<head>

<title>Blog</title>

<%= stylesheet_link_tag “application” %>

<%= javascript_include_tag “application” %>

<%= csrf_meta_tags %>

</head>

<body style=“background: #EEEEEE;”>

 

<%= yield %>

 

</body>

</html>

Now when you refresh the /posts page, you’ll see a gray background to the page. This same gray background will be used throughout all the views for posts.现在你刷新/posts页面,你将会看到一个灰色的页面背景。并且相同的灰色背景将会使用在posts的所有视图中。

6.9 Creating New Posts

Creating a new post involves two actions. The first is the new action, which instantiates an empty Post object:创建一个new post 包含两个actions。首先是new action,它会实例化一个空的Post对象:

def new

@post = Post.new

 

respond_to do |format|

format.html # new.html.erb

format.json { render :json => @post }

end

end

The new.html.erb view displays this empty Post to the user: 这个new.html.erb视图显示这个空的post给用户:

<h1>New post</h1>

 

<%= render ‘form’ %>

 

<%= link_to ‘Back’, posts_path %>

The <%= render ‘form’ %> line is our first introduction to partials in Rails.<%= render ‘form’ %>是我们第一个介绍的RailspartialsA partial is a snippet of HTML and Ruby code that can be reused in multiple locations.一个partial是一个HTML代码片段和Ruby代码的组合可以在多目标对象中重用。(类似于djangoinclude ‘other.html’In this case, the form used to make a new post, is basically identical to a form used to edit a post, both have text fields for the name and title and a text area for the content with a button to make a new post or update the existing post.在本例中,form用于创建new post,它相当于一个用于编辑一个post的表单,这个表单有一个name text fields title text fields 以及一个contenttext area还有一个用于添加一个新的post或者更新已经存在的post的按钮。

If you take a look at views/posts/form.html.erb file, you will see the following:如果你看一下views/posts/form.html.erb这个文件,你将会发现下面的内容:

<%= form_for(@post) do |f| %>

<% if @post.errors.any? %>

<div id=“error_explanation”>

<h2><%= pluralize(@post.errors.count, “error”) %> prohibited this post from being saved:</h2>

<ul>

<% @post.errors.full_messages.each do |msg| %>

<li><%= msg %></li>

<% end %>

</ul>

</div>

<% end %>

<div>

<%= f.label :name %><br />

<%= f.text_field :name %>

</div>

<div>

<%= f.label :title %><br />

<%= f.text_field :title %>

</div>

<div>

<%= f.label :content %><br />

<%= f.text_area :content %>

</div>

<div>

<%= f.submit %>

</div

<% end %>

This partial receives all the instance variables defined in the calling view file, so in this case, the controller assigned the new Post object to @post and so, this is available in both the view and partial as @post.这个partial接收在view文件中定义的所有的实例变量,因此在本例中,controller申请新的Post对象给@post@postviewipartial都是可用的。

For more information on partials, refer to the LayoutsandRenderinginRails guide.有关partials的更多信息,参考LayoutsandRenderinginRails指导。

The form_for block is used to create an HTML form.form_for代码块用于创建一个HTML表单。Within this block, you have access to methods to build various controls on the form. 在这个代码块中你可以在访问方法的基础上在表单上创建各种控制。For example, f.text_field :name tells Rails to create a text input on the form, and to hook it up to the name attribute of the instance being displayed.比如,f.test_field :name 告诉Rails在表单中创建一个text inputYou can only use these methods with attributes of the model that the form is based on (in this case name, title, and content).form使用的方法基于model的相对应的字段属性(类型如text_field or text_area)(例如本例中的name,title,content)。Rails uses form_for in preference偏好优先to having you write raw HTML because the code is more succinct#简洁, and because it explicitly明确ties关系the form to a particular model instance.Rails使用(偏向于使用)form_for列出你要输入的HTML行因为这样代码更加简洁,并却这样使得formparticular model实例关系更加明显。

The form_for block is also smart enough to work out if you are doing a New Post or an Edit Post action, and will set the form action tags and submit button names appropriately in the HTML output.form_for代码块同样也足够你定制你的New PostEdit Post action,并且将会设置form action标签和在HTML输出中显示的提交按钮名称。

If you need to create an HTML form that displays arbitrary#任意fields, not tied to a model, you should use the form_tag method, which provides shortcuts for building forms that are not necessarily tied to a model instance.如果你需要创建一个HTML表单显示任意的域,而不绑定到model字段中,你应该使用form_tag方法,它快捷的保证了建立forms不必在绑定到一个model实例。

When the user clicks the Create Post button on this form, the browser will send information back to the create method of the controller (Rails knows to call the create method because the form is sent with an HTTP POST request; thats one of the conventions that I mentioned earlier):当用户点击这张表单上面的创建Post按钮,浏览器将会发送信息——controller的方法回服务器(Rails知道调用create方法,因为form是以HTTP POST请求发送,这是我随后提到的一种协议之一)

def create

@post = Post.new(params[:post])

respond_to do |format|

if @post.save

format.html { redirect_to @post, :notice => ‘Post was successfully created.’ }

format.json { render :json => @post, :status => :created, :location => @post }

else

format.html { render :action => “new” }

format.json { render :json => @post.errors, :status => :unprocessable_entity }

end

end

end

The create action instantiates a new Post object from the data supplied by the user on the form, which Rails makes available in the params hash.create action实例化一个新的Post对象,这个对象给form提供数据支持。After successfully saving the new post, create returns the appropriate format that the user has requested (HTML in our case).当成功的保存了新postcreate返回用户请求的适当的格式(在本例中是HTML)。It then redirects the user to the resulting post show action and sets a notice to the user that the Post was successfully created.然后重定向用户页面到结果显示的post show action页面并且给出提示Post成功的创建了。

If the post was not successfully saved, due to a validation error, then the controller returns the user back to the new action with any error messages so that the user has the chance to fix the error and try again.如果post没有保存成功,是因为(数据)验证错误,然后controller控制用户页面回到new action(包含验证错误新息)给用户。

The “Post was successfully created.” message is stored inside of the Rails flash hash, (usually just called the flash) so that messages can be carried#over to another action, providing the user with useful information on the status of their request. “Post was successfully created.” 这条消息被存储在Railsflashhash表中,(通常之叫它flash)因此消息可以转载到另一个action,在请求状态中提供有用的信息给用户。In the case of create, the user never actually sees any page rendered during the Post creation process, because it immediately redirects to the new Post as soon Rails saves the record.在这个新建例子(数据验证失败)中,用户实际上从来不看任何在页面创建进程中的渲染页面,因为它立刻重定向页面到new PostRails保存了这个记录。The Flash carries over a message to the next action, so that when the user is redirected back to the show action, they are presented with a message saying “Post was successfully created.”Flash装载消息到接下来的action,因此当用户被重定向到了show action,他们立刻收到了一条消息Post was successfully created.”

6.10 Showing an Individual Post显示一条单个的Post

When you click the show link for a post on the index page, it will bring you to a URL like http://localhost:3000/posts/1. 当你在posts 的主页面点击一个postshow这个超链接,他将会产生一个url http://localhost:3000/posts/1Rails interprets解释this as a call to the show action for the resource, and passes in 1 as the :id parameter.Rails解释这是一个到show actionresource 调用。Here’s the show action:这里是show action

def show

@post = Post.find(params[:id])

respond_to do |format|

format.html # show.html.erb

format.json { render :json => @post }

end

end

The show action uses Post.find to search for a single record in the database by its id value.这里的show action使用Post.find通过对应记录的id来查找单个记录。After finding the record, Rails displays it by using show.html.erb:当找到记录,Rails使用show.html.erb来显示它:

<p id=“notice”><%= notice %></p>

<p>

<b>Name:</b>

<%= @post.name %>

</p>

<p>

<b>Title:</b>

<%= @post.title %>

</p>

<p>

<b>Content:</b>

<%= @post.content %>

</p>

<%= link_to ‘Edit’, edit_post_path(@post) %> |

<%= link_to ‘Back’, posts_path %>

6.11 Editing Posts编辑Posts

Like creating a new post, editing a post is a two-part process.类似创建一个新的post,编辑一个post也(分为)两部分。The first step is a request to edit_post_path(@post) with a particular post. This calls the edit action in the controller:首先是到edit_post_path(@post)请求一个特定的post。这里是调用的在controller中的edit action

def edit

@post = Post.find(params[:id])

end

After finding the requested post, Rails uses the edit.html.erb view to display it:在找到了请求的postRails使用edit.html.erb试图来显示它:

<h1>Editing post</h1>

 

<%= render ‘form’ %>

 

<%= link_to ‘Show’, @post %> |

<%= link_to ‘Back’, posts_path %>

Again, as with the new action, the edit action is using the form partial, this time however, the form will do a PUT action to the PostsController and the submit button will displayUpdate Post再一次的,就像new actionedit action也使用form部分,这次有所不同,form将会提交一个PUT actionPostsController并且提交按钮将会显示Update Post

Submitting the form created by this view will invoke调用the update action within the controller:提交的form由上面这个视图创建的并且还会调用controller中的update action

def update

@post = Post.find(params[:id])

respond_to do |format|

if @post.update_attributes(params[:post])

format.html { redirect_to @post, :notice => ‘Post was successfully updated.’ }

format.json { head :ok }

else

format.html { render :action => “edit” }

format.json { render :json => @post.errors, :status => :unprocessable_entity }

end

end

end

In the update action, Rails first uses the :id parameter passed back from the edit view to locate the database record thats being edited.update action中,Rails首先使用:id参数从edit view(传值到)数据库记录下刚才编辑的内容。The update_attributes#更新model的属性call then takes the rest of the parameters from the request and applies them to this record. update_attributes在应用一些(更多)参数的来自request的数据到recode时被调用。If all goes well, the user is redirected to the posts show view. 如果一切成功,用户会被重定向到postshow视图。If there are any problems, its back to the edit view to correct them.如果期间发生了任何错误,它将回到edit视图并(要求)改正他们。

6.12 Destroying a Post 摧毁一个post

Finally, clicking one of the destroy links sends the associated id to the destroy action:最后,点击一个destroy链接发送相关的iddestroy动作:

def destroy

@post = Post.find(params[:id])

@post.destroy

 

respond_to do |format|

format.html { redirect_to posts_url }

format.json { head :ok }

end

end

The destroy method of an Active Record model instance removes the corresponding record from the database.这个destroyActive Recordmodel的实例(功能是)从数据库中移除相应的记录。After that’s done, there isn’t any record to display, so Rails redirects the user’s browser to the index view for the model.当这个(操作)完成,这里没有任何记录显示,因此Rails重定向用户的浏览器到model的主页视图。

7 Adding a Second Model添加第二个Modelcomment

Now that you’ve seen how a model built with scaffolding looks like, it’s time to add a second model to the application.你已经知道了通过scaffolding生成的model看起来是怎样的。The second model will handle comments on blog posts.第二个model用来处理blog post的评论。

7.1 Generating a Model构造一个model

Models in Rails use a singular name, and their corresponding database tables use a plural name. Rails 中的Models使用一个单数名称,同时它们相关的数据库表使用一个复数名称。For the model to hold comments, the convention is to use the name Comment.对于评论在models中的代名词,习惯上使用的的是CommentEven if you don’t want to use the entire apparatus set up by scaffolding, most Rails developers still use generators to make things like models and controllers.即使你不想完完全全的使用scaffolding,大多数的Rails仍然使用生成器来做这些事情比如modelscontrollersTo create the new model, run this command in your terminal:要创建一个新的model,在终端中运行下面这条命令:

rails generate model Comment commenter:string body:text post:references #references引用

This command will generate four files:这条命令将会生成四个文件:

  • app/models/comment.rb – The model 模型
  • db/migrate/20111108080402_create_comments.rb – The migration 数据迁移
  • test/unit/comment_test.rb andtest/fixtures/comments.yml – The test harness. 测试工具

First, take a look at comment.rb:首先,看一看comment.rb:

class Comment < ActiveRecord::Base

belongs_to :post

end

This is very similar to the post.rb model that you saw earlier.这和你刚刚看到post.rb很近似。The difference is the line belongs_to :post, which sets up an Active Record association. 不同的是这行belongs_to :post,他会安装一个Active Record associationYou’ll learn a little about associations in the next section of this guide.你将会在接下来的guide学习一点有关associations的内容。

In addition to the model, Rails has also made a migration to create the corresponding database table:除了模型,Rails同样也产生了一个migration来创建相应的数据库表单:

class CreateComments < ActiveRecord::Migration

def change

create_table :comments do |t|

t.string :commenter

t.text :body

t.references :post

t.timestamps

end

add_index :comments, :post_id

end

end

The t.references line sets up a foreign key column for the association between the two models.对于t.references这行,会在两个models之间生成一个外键列从而形成一个关系(组合)。And the add_index line sets up an index for this association column. Go ahead and run the migration:而且add_index line生成一个首页关联到这个关系行:

$ rake db:migrate

Rails is smart enough to only execute the migrations that have not already been run against the current database, so in this case you will just see:Rails能够智能的只针对对没有被运行过的表单,执行migrations生成当前的数据库,因此这里你只会看到:

7.2 Associating Models关联models

Active Record associations let you easily declare the relationship between two models. In the case of comments and posts, you could write out the relationships this way:Active Record associations让你很容易的申明两个models之间的关系。在本例中的commentsposts,你可以写出这样描述关系:

  • Each comment belongs to one post 一条comment对应于一个post
  • One post can have many comments 一个post可以对应于多个comments

In fact, this is very close to the syntax that Rails uses to declare this association.实际上,这也很接近Rails申明的association 的语法。You’ve already seen the line of code inside the Comment model that makes each comment belong to a Post:你已经看到了在Comment model中的使每个comment对应于一个post的代码。

You’ll need to edit the post.rb file to add the other side of the association:你将会需要编辑post.rb文件来添加其他association 盟友。

class Post < ActiveRecord::Base

validates :name, :presence => true

validates :title, :presence => true,

:length => { :minimum => 5 }

 

has_many :comments

end

These two declarations enable a good bit of automatic behavior. For example, if you have an instance variable @post containing a post, you can retrieve all the comments belonging to that post as the array @post.comments.

For more information on Active Record associations, see the ActiveRecordAssociations guide.

7.3 Adding a Route for CommentsComments添加路由

As with the home controller, we will need to add a route so that Rails knows where we would like to navigate to see comments.作为home controller,我们将还需要添加一个路由让Rails知道我们导航到哪里可以看到评论。Open up the config/routes.rb file again, you will see an entry that was added automatically for posts near the top by the scaffold generator, resources :posts, edit it as follows:再次打开config/routes.rb文件,你将会看到scaffold创建器在顶部为posts自动添加的入口,resources :posts,把它改成如下:

resources :posts do

resources :comments

end

This creates comments as a nested resource within posts.这里把comments作为一个嵌套资源放在posts中。This is another part of capturing the hierarchical relationship that exists between posts and comments.这是在存在的postscomments的分层关系的表现。

For more information on routing, see the RailsRoutingfromtheOutsideIn guide.关于routing的更多的信息,查看RailsRoutingfromtheOutsideIn guide

7.4 Generating a Controller构造一个Controller

With the model in hand, you can turn your attention to creating a matching controller.model已经到手了,你可以把你的注意力放到创建一个匹配的controller上了。Again, there’s a generator for this:类似的,像这样构造:

$ rails generate controller Comments

This creates six files and one empty directory:这里新建了6个文件和一个空目录。

  • app/controllers/comments_controller.rb – The controller
  • app/helpers/comments_helper.rb – A view helper file
  • test/functional/comments_controller_test.rb – The functional tests for the controller
  • test/unit/helpers/comments_helper_test.rb – The unit tests for the helper
  • app/views/comments/ – Views of the controller are stored here
  • app/assets/stylesheets/comment.css.scss – Cascading style sheet for the controller
  • app/assets/javascripts/comment.js.coffee – CoffeeScript for the controller

Like with any blog, our readers will create their comments directly after reading the post, and once they have added their comment, will be sent back to the post show page to see their comment now listed.就像大多数blog,我们的读者将会直接发表他们的评论在他们阅读post的时候,并且一旦他们添加评论成功,将会回到postshow页面去查看他们刚刚列出的评论。Due to this, our CommentsController is there to provide a method to create comments and delete SPAM comments when they arrive.正因为这样(的考虑),我们的CommentsController如下,它提供一个方法来创建comments和删除垃圾评论。

<p><%= notice %></p>

 

<p>

<b>Name:</b>

<%= @post.name %>

</p>

 

<p>

<b>Title:</b>

<%= @post.title %>

</p>

 

<p>

<b>Content:</b>

<%= @post.content %>

</p>

 

<h2>Add a comment:</h2>

<%= form_for([@post, @post.comments.build]) do |f| %>

<div>

<%= f.label :commenter %><br />

<%= f.text_field :commenter %>

</div>

<div>

<%= f.label :body %><br />

<%= f.text_area :body %>

</div>

<div>

<%= f.submit %>

</div>

<% end %>

 

<%= link_to ‘Edit Post’, edit_post_path(@post) %> |

<%= link_to ‘Back to Posts’, posts_path %> |

This adds a form on the Post show page that creates a new comment, which will call the CommentsController create action, so let’s wire that up:这里添加一个formsPost show页面用来创建一个新的评论,它将会调用CommentsControllercreat action,因此让我们补充上下面的内容:

class CommentsController < ApplicationController

def create

@post = Post.find(params[:post_id])

@comment = @post.comments.create(params[:comment])

redirect_to post_path(@post)

end

end

You’ll see a bit more complexity here than you did in the controller for posts.这里你看到的会比你在controller中为posts做的要复杂点。That’s a side-effect of the nesting that you’ve set up; each request for a comment has to keep track#踪迹of the post to which the comment is attached, thus the initial find action to the Post model to get the post in question.那就是你刚刚你刚补充的副作用的根源;每个面向comment的请求都保持了它所依附的post的踪迹,因此这样初始化find action的时候匹配相应的post model(时)得到了答案。

In addition, the code takes advantage of some of the methods available for an association.此外,上面的代码带来的好处就是使得一些对于association的方法可用。We use the create method on @post.comments to create and save the comment.我们使用@post.comments中的create方法来新建和保存commentThis will automatically link the comment so that it belongs to that particular post.这里将会自动连接到link使得comment依附于指定的post

Once we have made the new comment, we send the user back to the original post using the post_path(@post) helper.一旦我们评论过后,我们使用post_path(@post)助手导引用户到先前的postAs we have already seen, this calls the show action of the PostsController which in turn renders the show.html.erb template. 正如我们已经看到的,这里调用PostsControllershow action它将反过来渲染show.html.erb 模板。This is where we want the comment to show, so let’s add that to the app/views/posts/show.html.erb.这里也是我们想让comment显示的地方,因此让我们添加(那些代码)到app/views/posts/show.html.erb

<p><%= notice %></p>

 

<p>

<b>Name:</b>

<%= @post.name %>

</p>

 

<p>

<b>Title:</b>

<%= @post.title %>

</p>

 

<p>

<b>Content:</b>

<%= @post.content %>

</p>

 

<h2>Comments</h2>

<% @post.comments.each do |comment| %>

<p>

<b>Commenter:</b>

<%= comment.commenter %>

</p>

 

<p>

<b>Comment:</b>

<%= comment.body %>

</p>

<% end %>

 

<h2>Add a comment:</h2>

<%= form_for([@post, @post.comments.build]) do |f| %>

<div>

<%= f.label :commenter %><br />

<%= f.text_field :commenter %>

</div>

<div>

<%= f.label :body %><br />

<%= f.text_area :body %>

</div>

<div>

<%= f.submit %>

</div>

<% end %>

 

<br />

 

<%= link_to ‘Edit Post’, edit_post_path(@post) %> |

<%= link_to ‘Back to Posts’, posts_path %> |

Now you can add posts and comments to your blog and have them show up in the right places.现在你可以添加postscomments到你的blog同时随后他们会在相应的地方显示出来。

8 Refactoring重构

Now that we have Posts and Comments working, if we take a look at the app/views/posts/show.html.erb template, it’s getting long and awkward. 现在我们已经有PostsComments开始工作了,如果我们注意一下app/views/posts/show.html.erb 模板,发现它变得太长而且很别扭。We can use partials to clean this up.我们可以使用partials来整理它。

8.1 Rendering Partial(局部)Collections

First we will make a comment partial to extract showing all the comments for the post. 首先我们会创建一个comment partial来专门显示post的所有的commentsCreate the file app/views/comments/comment.html.erb and put the following into it:创建app/views/comments/comment.html.erb文件并输入下面的代码:

<p>

<b>Commenter:</b>

<%= comment.commenter %>

</p>

 

<p>

<b>Comment:</b>

<%= comment.body %>

</p>

Then in the app/views/posts/show.html.erb you can change it to look like the following:然后在app/views/posts/show.html.erb你可以相应的这样更改:

<p class=“notice”><%= notice %></p>

 

<p>

<b>Name:</b>

<%= @post.name %>

</p>

 

<p>

<b>Title:</b>

<%= @post.title %>

</p>

 

<p>

<b>Content:</b>

<%= @post.content %>

</p>

 

<h2>Comments</h2>

<%= render @post.comments %>

 

<h2>Add a comment:</h2>

<%= form_for([@post, @post.comments.build]) do |f| %>

<div class=“field”>

<%= f.label :commenter %><br />

<%= f.text_field :commenter %>

</div>

<div class=“field”>

<%= f.label :body %><br />

<%= f.text_area :body %>

</div>

<div class=“actions”>

<%= f.submit %>

</div>

<% end %>

 

<br />

 

<%= link_to ‘Edit Post’, edit_post_path(@post) %> |

<%= link_to ‘Back to Posts’, posts_path %> |

This will now render the partial in app/views/comments/comment.html.erb once for each comment that is in the @post.comments collection.这里会对@post.comments的每一个comment渲染app/views/comments/comment.html.erb模板。As the render method iterates over the @post.comments collection, it assigns each comment to a local variable named the same as the partial, in this case comment which is then available in the partial for us to show.当渲染方法迭代@post.comments收集器的时候,它声明每个comment为本地变量命名和partial相同(这里为comment),通过这样在partial中的comment就可以显示给我们的用户了。

8.2 Rendering a Partial Form

Lets also move that new comment section out to its own partial.同样让我们移动new comment部分到它自己的地方吧。Again, you create a file app/views/comments/form.html.erb and in it you put:类似的,创建一个文件app/views/comments/form.html.erb并且在里面放入下面代码:

<%= form_for([@post, @post.comments.build]) do |f| %>

<div class=“field”>

<%= f.label :commenter %><br />

<%= f.text_field :commenter %>

</div>

<div class=“field”>

<%= f.label :body %><br />

<%= f.text_area :body %>

</div>

<div class=“actions”>

<%= f.submit %>

</div>

<% end %>

Then you make the app/views/posts/show.html.erb look like the following:接着你这样修改app/views/posts/show.html.erb文件:

<p class=“notice”><%= notice %></p>

 

<p>

<b>Name:</b>

<%= @post.name %>

</p>

 

<p>

<b>Title:</b>

<%= @post.title %>

</p>

 

<p>

<b>Content:</b>

<%= @post.content %>

</p>

 

<h2>Comments</h2>

<%= render @post.comments %>

 

<h2>Add a comment:</h2>

<%= render “comments/form” %>

 

<br />

 

<%= link_to ‘Edit Post’, edit_post_path(@post) %> |

<%= link_to ‘Back to Posts’, posts_path %> |

The second render just defines the partial template we want to render, comments/form, Rails is smart enough to spot the forward slash in that string and realize that you want to render the form.html.erb file in the app/views/comments directory.第二个render仅仅定义了一个我们想渲染的partial template comments/formRails可以智能的识别字符串代表的含义,并且知道你是想render form.html.erb模板。

The @post object is available to any partials rendered in the view because we defined it as an instance variable.@post可以在任何的视图中partials rendered,因为我们把它定义成的实例变量。

9 Deleting Comments

Another important feature on a blog is being able to delete SPAM comments.另一个重要的功能就是可以删除垃圾评论。To do this, we need to implement a link of some sort in the view and a DELETE action in the CommentsController.要达到这样的效果,我们需要在view中实现某种链接和在CommentsController中的DELETE动作。

So first, lets add the delete link in the app/views/comments/comment.html.erb partial:首先,在app/views/comments/comment.html.erb partial中添加delete link

<p>

<b>Commenter:</b>

<%= comment.commenter %>

</p>

 

<p>

<b>Comment:</b>

<%= comment.body %>

</p>

 

<p>

<%= link_to ‘Destroy Comment’, [comment.post, comment],

:confirm => ‘Are you sure?’,

:method => :delete %>

</p>

Clicking this new “Destroy Comment” link will fire off a DELETE /posts/:id/comments/:id to our CommentsController, which can then use this to find the comment we want to delete, so let’s add a destroy action to our controller:点击Destroy Comment”link将会发送DELETE /posts/:id/comments/:id到我们的CommentsControllerCommentsController将会利用刚刚收到的(消息)找到我们想删除哪条评论,因此让我们接着添加一个destroy action到我们的controller

class CommentsController < ApplicationController

 

def create

@post = Post.find(params[:post_id])

@comment = @post.comments.create(params[:comment])

redirect_to post_path(@post)

end

 

def destroy

@post = Post.find(params[:post_id])

@comment = @post.comments.find(params[:id])

@comment.destroy

redirect_to post_path(@post)

end

 

end

The destroy action will find the post we are looking at, locate the comment within the @post.comments collection, and then remove it from the database and send us back to the show action for the post.destroy action将会找到那个我们正在阅读的post,并且定位comment@post.comments收集器,然后从数据库remove它,最后传回到postshow action

9.1 Deleting Associated Objects删除关联对象

If you delete a post then its associated comments will also need to be deleted. 如果你删除一个了post,那么与之相关联的comments也需要被删除。Otherwise they would simply occupy space in the database.否则他们将会只是在数据库中占用空间(别无它用)。Rails allows you to use the dependent option of an association to achieve this. Modify the Post model, app/models/post.rb, as follows:Rails允许你通过关系的依赖选项完成(上述功能)。修改Post model

class Post < ActiveRecord::Base

validates :name, :presence => true

validates :title, :presence => true,

:length => { :minimum => 5 }

has_many :comments, :dependent => :destroy

end

10 Security

If you were to publish your blog online, anybody would be able to add, edit and delete posts or delete comments.如果你就这样publish你的blog在互联网,任何人都可以添加,编辑和删除post或者删除comments

Rails provides a very simple HTTP authentication system that will work nicely in this situation.Rails提供了一个非常简单的HTTP认证系统在这样的情况下会非常适合。

In the PostsController we need to have a way to block access to the various actions if the person is not authenticated, here we can use the Rails http_basic_authenticate_with method, allowing access to the requested action if that method allows it.PostsController中我们需要一个方法来阻止没有通过认证的用户的操作,这里我们可以使用Railshttp_basic_authenticate_with这个方法,准许方法允许的请求的action

To use the authentication system, we specify it at the top of our PostsController, in this case, we want the user to be authenticated on every action, except for index and show, so we write that:要是用这个认证系统,我们需要在PostsController 的顶部在指定(即引用)它,这样我们希望用户在进行每个action的时候都是通过授权的,除了indexshow,因此我们这样写:

class PostsController < ApplicationController

 

http_basic_authenticate_with :name => “dhh”, :password => “secret”, :except => :index

 

# GET /posts

# GET /posts.json

def index

@posts = Post.all

We also only want to allow authenticated users to delete comments, so in the CommentsController we write:我们同样希望只有授权用户能够删除评论,因此在CommentsController这样写:

class CommentsController < ApplicationController

 

http_basic_authenticate_with :name => “dhh”, :password => “secret”, :only => :destroy

 

def create

@post = Post.find(params[:post_id])

Now if you try to create a new post, you will be greeted with a basic HTTP Authentication challenge.现在如果你尝试创建一个新的post,你将会迎来一个基于HTTP认证的挑战。

11 Building a Multi-Model Form构建一个多模型表单

Another feature of your average blog is the ability to tag posts. To implement this feature your application needs to interact with more than one model on a single form. Rails offers support for nested forms.另一个功能你的平衡的blog是能够给posts添加tag。要想在你的程序中实现这个功能需要在一个form中与超过一个model互动。Rails提供了嵌套forms

To demonstrate this, we will add support for giving each post multiple tags, right in the form where you create the post. First, create a new model to hold the tags:为了演示这个(功能),你将会在你创建postform中添加post的多tag支持。首先创建一个new model来存放tags

$ rails generate model tag name:string post:references

Again, run the migration to create the database table:再次运行migration来创建数据库表单:

$ rake db:migrate

Next, edit the post.rb file to create the other side of the association, and to tell Rails (via the accepts_nested_attributes_for macro) that you intend to edit tags via posts:接下来:编辑post.rb文件来创建来创建另一个成员,并且告诉Rails(通过the accepts_nested_attributes_for 宏)你打算通过posts form来编辑tags

class Post < ActiveRecord::Base

validates :name, :presence => true

validates :title, :presence => true

validates :content,:presence => true,

:length => { :minimum => 5 }

 

has_many :comments, :dependent => :destroy

has_many :tags

 

accepts_nested_attributes_for :tags, :allow_destroy => :true,

:reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }

end

The :allow_destroy option on the nested attribute declaration tells Rails to display aremovecheckbox on the view that youll build shortly.对于:allow_destroy嵌套属性的声明是告诉Rails显示一个remove复选框在视图中那样你可以快速创建(tags)。The :reject_if option prevents saving new tags that do not have any attributes filled in.对于:reject_if保证不保存没有任何内容的tags

We will modify views/posts/form.html.erb to render a partial to make a tag:我们将要修改views/posts/form.html.erbrenderform的)一部分来创建tag

<% @post.tags.build %>

<%= form_for(@post) do |post_form| %>

<% if @post.errors.any? %>

<div id=“errorExplanation”>

<h2><%= pluralize(@post.errors.count, “error”) %> prohibited this post from being saved:</h2>

<ul>

<% @post.errors.full_messages.each do |msg| %>

<li><%= msg %></li>

<% end %>

</ul>

</div>

<% end %>

 

<div class=“field”>

<%= post_form.label :name %><br />

<%= post_form.text_field :name %>

</div>

<div class=“field”>

<%= post_form.label :title %><br />

<%= post_form.text_field :title %>

</div>

<div class=“field”>

<%= post_form.label :content %><br />

<%= post_form.text_area :content %>

</div>

<h2>Tags</h2>

<%= render :partial => ‘tags/form’,

:locals => {:form => post_form} %>

<div class=“actions”>

<%= post_form.submit %>

</div>

<% end %>

Note that we have changed the f in form_for(@post) do |f| to post_form to make it easier to understand what is going on.注意:我们已经更改form_for(@post) do |f|form_for(@post) do |post_form|这样会更加容易明白是怎么回事。

This example shows another option of the render helper, being able to pass in local variables, in this case, we want the local variable form in the partial to refer to the post_form object.这个例子在render helper中使用另个方式(使用f),是为了说明我们希望的是在form中使用局部变量指向的post_form对象。

We also add a @post.tags.build at the top of this form. This is to make sure there is a new tag ready to have its name filled in by the user. If you do not build the new tag, then the form will not appear as there is no new Tag object ready to create.我们还在form的顶部添加@post.tags.build。这里是为了确保每个新的tag都被用户填上了name。如果你不创建新tagform将不会显示它。

Now create the folder app/views/tags and make a file in there called form.html.erb which contains the form for the tag:现在创建一个app/views/tags文件夹并且在里面新建一个form.html.erb包含以下内容:

<%= form.fields_for :tags do |tag_form| %>

<div class=“field”>

<%= tag_form.label :name, ‘Tag:’ %>

<%= tag_form.text_field :name %>

</div>

<% unless tag_form.object.nil? || tag_form.object.new_record? %>

<div class=“field”>

<%= tag_form.label :_destroy, ‘Remove:’ %>

<%= tag_form.check_box :_destroy %>

</div>

<% end %>

<% end %>

Finally, we will edit the app/views/posts/show.html.erb template to show our tags.最后编辑app/views/posts/show.html.erb模板显示我们的tags

<p class=“notice”><%= notice %></p>

 

<p>

<b>Name:</b>

<%= @post.name %>

</p>

 

<p>

<b>Title:</b>

<%= @post.title %>

</p>

 

<p>

<b>Content:</b>

<%= @post.content %>

</p>

 

<p>

<b>Tags:</b>

<%= @post.tags.map { |t| t.name }.join(“, ”) %>

</p>

 

<h2>Comments</h2>

<%= render @post.comments %>

 

<h2>Add a comment:</h2>

<%= render “comments/form” %>

 

 

<%= link_to ‘Edit Post’, edit_post_path(@post) %> |

<%= link_to ‘Back to Posts’, posts_path %> |

With these changes in place, youll find that you can edit a post and its tags directly on the same view.通过这写修改,你会发现你可以直接在post form中编辑tags

However, that method call @post.tags.map { |t| t.name }.join(“, ”) is awkward, we could handle this by making a helper method.另外,@post.tags.map { |t| t.name }.join(“, ”)这个方法很别扭,我们可以通过编写一个helper method

###上面都还只能一次创建一个tagpost form

12 View Helpers

View Helpers live in app/helpers and provide small snippets of reusable code for views.View Helpers放置在app/helpers,它提供了可重用的小代码片段给viewIn our case, we want a method that strings a bunch of objects together using their name attribute and joining them with a comma.在本例,我们想要一个方法把(tag)放在一起(一个字符串中),并且使用逗号分割。As this is for the Post show template, we put it in the PostsHelper.要想这样在Post show模板,我们在PostHelper中写入:

Now you can edit the view in app/views/posts/show.html.erb to look like this:现在你可以在app/views/posts/show.html.erb中更改:

<p class=“notice”><%= notice %></p>

 

<p>

<b>Name:</b>

<%= @post.name %>

</p>

 

<p>

<b>Title:</b>

<%= @post.title %>

</p>

 

<p>

<b>Content:</b>

<%= @post.content %>

</p>

 

<p>

<b>Tags:</b>

<%= join_tags(@post) %>

</p>

 

<h2>Comments</h2>

<%= render @post.comments %>

 

<h2>Add a comment:</h2>

<%= render “comments/form” %>

 

 

<%= link_to ‘Edit Post’, edit_post_path(@post) %> |

<%= link_to ‘Back to Posts’, posts_path %> |

13 What’s Next?接下来做什么呢?

Now that you’ve seen your first Rails application, you should feel free to update it and experiment on your own. But you don’t have to do everything without help.现在你已经看到了你的第一个Rails应用程序,你应该可以很轻松的继续更新它或者试验一下你的想法。As you need assistance getting up and running with Rails, feel free to consult these support resources:当你在更新和运行Rails的时候需要援助,咨询下面推荐的资源会让你感到轻松:

Rails also comes with built-in help that you can generate using the rake command-line utility:Rails同样也带有内置的帮助你可以使用rake命令实用工具在你的应用程序中创建帮助文档:

  • Running rake doc:guides will put a full copy of the Rails Guides in the doc/guides folder of your application. Open doc/guides/index.html in your web browser to explore the Guides. 运行rake doc:guides将会输出所有Rails Guides的文档到你的应用程序中的doc/guides中。在你的浏览器中打开/guides/index.html浏览Guides
  • Running rake doc:rails will put a full copy of the API documentation for Rails in the doc/api folder of your application. Open doc/api/index.html in your web browser to explore the API documentation. 运行 rake doc:rails将会输出所有Rails API 的文档到你的应用程序中的doc/api中。

因为redcloth的问题文档支持有点故障,虽然找到了一种解决方法但是不够完美以待官方或者来人修复。

14 Configuration Gotchas配置陷阱

The easiest way to work with Rails is to store all external data as UTF-8.Rails使用Rails最简单的工作方式是存储所有的外部数据为UTF-8编码。If you don’t, Ruby libraries and Rails will often be able to convert your native data into UTF-8, but this doesn’t always work reliably, so you’re better off ensuring that all external data is UTF-8.如果不那样做,Ruby librariesRails通才会转换你的自然数据成UTF-8编码,但是这样不是很可靠,因此你最好保证所有的外部数据是UTF-8编码。

If you have made a mistake in this area, the most common symptom is a black diamond with a question mark inside appearing in the browser. 如果你在这里犯了错误,一般的症状就是在浏览器中出现钻石符号(可能是^)变成了问号。Another common symptom is characters like “ü” appearing instead of “ü”. 另一个普遍症状是ü”变成了ü”Rails takes a number of internal内部steps to mitigate减轻common causes of these problems that can be automatically detected检测and corrected. However, if you have external data that is not stored as UTF-8, it can occasionally偶尔result in these kinds of issues that cannot be automatically detected by Rails and corrected更正.

Two very common sources of data that are not UTF-8:两种非常普遍的不是UTF-8 编码的源数据:

  • Your text editor: Most text editors (such as Textmate), default to saving files as UTF-8. If your text editor does not, this can result in special characters that you enter in your templates (such as é) to appear as a diamond with a question mark inside in the browser. This also applies to your I18N translation files. Most editors that do not already default to UTF-8 (such as some versions of Dreamweaver) offer a way to change the default to UTF-8. Do so.
  • Your database. Rails defaults to converting data from your database into UTF-8 at the boundary. However, if your database is not using UTF-8 internally, it may not be able to store all characters that your users enter. For instance, if your database is using Latin-1 internally, and your user enters a Russian, Hebrew, or Japanese character, the data will be lost forever once it enters the database. If possible, use UTF-8 as the internal storage of your database.