Rails有一个很好的实践或者建议即convention over config,或者coding by convention,中文叫做按惯例编程,在放弃一些灵活性的前提下,可以享受到一些大师级的最优实践,这是它的出发点。在Rails里不按惯例编程,是或受到惩罚的,以下就是一个例子:
$rails new myapp -m https://github.com/RailsApps/rails3-application-templates/raw/master/rails3-mongoid-devise-template.rb -T -O
创建一个app,第一步是用rake spec cucumber检查是否有问题:(如果有问题,本博有文章已经介绍了如何搞定)
$rake spec cucumber
创建一个model:
$rails g model Post title:string
执行spec/cucumber(这也是一个convention):
$rake spec cucumber
OK. So far so good. 当创建controller的时候就有可能出问题了:
$rails g controller Post index show new create
请大家注意,这里我写的是Post,而其实应该是Posts,但Rails接受了这个命令,它甚至在routes里还加了几条:
Myapp::Application.routes.draw do
get "road/index"
get "road/show"
get "road/new"
get "road/create"
authenticated :user do
root :to => 'home#index'
end
root :to => "home#index"
devise_for :users
resources :users, :only => [:show, :index]
end
执行rake spec cucumber也都OK,一切似乎都挺正常,但当加入真实功能的时候,例如给new/create加实际功能,首先创建一个文件:app/views/post/_form.html.haml
= simple_form_for(@post) do |f|
= f.error_notification
.form-inputs
= f.input :title
.form-actions
= f.button :submit
再创建一个文件:app/views/post/new.html.haml
%h1 New post
= render 'form'
= link_to 'Back', post_path
至此问题才暴露:在浏览器打开http://localhost:3000/road/new时,报错:
no methods "posts_path" in _form.html #1
这说明rails的convention发挥了作用,要找posts_path而不是road_path,解决这个问题其实很简单:
1、将app/controllers/post_controller.rb换名成posts_controller.rb
2、修改spec/controllers/post_controller.rb及换名成posts_controller.rb
3、将app/views/post换名成posts
4、修改routes.rb:
Myapp::Application.routes.draw do
resources :posts
...
OK了。当然你也可以重新创建一个新的controller Posts,把原来的post相关的controller全部删除。本文提供的方法可以帮助你更深刻的理解rails创建model和controller背后发生了什么。