本教程假定您已阅读 Rails 入门指南,并了解一些 Rails 基础知识。
1 创建 Rails 应用程序
首先,让我们使用 rails new
命令创建一个简单的 Rails 应用程序。
我们将使用此应用程序来玩耍并发现本指南中描述的所有命令。
如果您还没有安装 rails gem,可以键入 gem install rails
来安装它。
1.1 rails new
我们要传递给 rails new
命令的第一个参数是应用程序名称。
$ rails new my_app
create
create README.md
create Rakefile
create config.ru
create .gitignore
create Gemfile
create app
...
create tmp/cache
...
run bundle install
Rails 将为这样一个微小的命令设置很多东西!我们现在拥有了完整的 Rails 目录结构,以及所有立即运行我们的简单应用程序所需代码。
如果您希望跳过某些文件的生成或跳过某些库,可以在 rails new
命令后添加以下任何参数。
参数 | 描述 |
---|---|
--skip-git |
跳过 git init、.gitignore 和 .gitattributes |
--skip-docker |
跳过 Dockerfile、.dockerignore 和 bin/docker-entrypoint |
--skip-keeps |
跳过源代码控制 .keep 文件 |
--skip-action-mailer |
跳过 Action Mailer 文件 |
--skip-action-mailbox |
跳过 Action Mailbox gem |
--skip-action-text |
跳过 Action Text gem |
--skip-active-record |
跳过 Active Record 文件 |
--skip-active-job |
跳过 Active Job |
--skip-active-storage |
跳过 Active Storage 文件 |
--skip-action-cable |
跳过 Action Cable 文件 |
--skip-asset-pipeline |
跳过资产管道 |
--skip-javascript |
跳过 JavaScript 文件 |
--skip-hotwire |
跳过 Hotwire 集成 |
--skip-jbuilder |
跳过 jbuilder gem |
--skip-test |
跳过测试文件 |
--skip-system-test |
跳过系统测试文件 |
--skip-bootsnap |
跳过 bootsnap gem |
--skip-dev-gems |
跳过添加开发 gem |
--skip-rubocop |
跳过 RuboCop 设置 |
这些只是 rails new
接受的一些选项。要查看完整的选项列表,请键入 rails new --help
。
1.2 预配置不同的数据库
创建新的 Rails 应用程序时,您可以选择指定应用程序将使用哪种数据库。这将为您节省几分钟时间,当然也节省很多按键操作。
让我们看看 --database=postgresql
选项将为我们做什么。
$ rails new petstore --database=postgresql
create
create app/controllers
create app/helpers
...
让我们看看它在 config/database.yml
中添加了什么内容。
# PostgreSQL. Versions 9.3 and up are supported.
#
# Install the pg driver:
# gem install pg
# On macOS with Homebrew:
# gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On Windows:
# gem install pg
# Choose the win32 build.
# Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem "pg"
#
default: &default
adapter: postgresql
encoding: unicode
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.net.cn/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
development:
<<: *default
database: petstore_development
...
它生成了与我们选择的 PostgreSQL 相对应的数据库配置。
2 命令行基础
有一些命令对您日常使用 Rails 至关重要。按照您可能使用它们的频率顺序,它们是
bin/rails console
bin/rails server
bin/rails test
bin/rails generate
bin/rails db:migrate
bin/rails db:create
bin/rails routes
bin/rails dbconsole
rails new app_name
您可以通过键入 rails --help
来获取您可用的 rails 命令列表,这些命令通常取决于您的当前目录。每个命令都有一个描述,应该可以帮助您找到需要的东西。
$ rails --help
Usage:
bin/rails COMMAND [options]
You must specify a command. The most common commands are:
generate Generate new code (short-cut alias: "g")
console Start the Rails console (short-cut alias: "c")
server Start the Rails server (short-cut alias: "s")
...
All commands can be run with -h (or --help) for more information.
In addition to those commands, there are:
about List versions of all Rails ...
assets:clean[keep] Remove old compiled assets
assets:clobber Remove compiled assets
assets:environment Load asset compile environment
assets:precompile Compile all the assets ...
...
db:fixtures:load Load fixtures into the ...
db:migrate Migrate the database ...
db:migrate:status Display status of migrations
db:rollback Roll the schema back to ...
db:schema:cache:clear Clears a db/schema_cache.yml file
db:schema:cache:dump Create a db/schema_cache.yml file
db:schema:dump Create a database schema file (either db/schema.rb or db/structure.sql ...
db:schema:load Load a database schema file (either db/schema.rb or db/structure.sql ...
db:seed Load the seed data ...
db:version Retrieve the current schema ...
...
restart Restart app by touching ...
tmp:create Create tmp directories ...
2.1 bin/rails server
bin/rails server
命令启动名为 Puma 的 Web 服务器,该服务器与 Rails 捆绑在一起。无论何时要通过 Web 浏览器访问您的应用程序,您都会使用它。
无需任何其他操作,bin/rails server
将运行我们全新的 Rails 应用程序。
$ cd my_app
$ bin/rails server
=> Booting Puma
=> Rails 8.0.0 application starting in development
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 6.4.0 (ruby 3.1.3-p185) ("The Eagle of Durango")
* Min threads: 5
* Max threads: 5
* Environment: development
* PID: 5295
* Listening on http://127.0.0.1:3000
* Listening on http://[::1]:3000
Use Ctrl-C to stop
只需三个命令,我们就启动了在端口 3000 上监听的 Rails 服务器。转到您的浏览器并打开 https://127.0.0.1:3000,您将看到一个正在运行的基本 Rails 应用程序。
您还可以使用别名“s”来启动服务器:bin/rails s
。
可以使用 -p
选项在不同的端口上运行服务器。可以使用 -e
更改默认开发环境。
$ bin/rails server -e production -p 4000
-b
选项将 Rails 绑定到指定的 IP 地址,默认情况下为 localhost。您可以通过传递 -d
选项将服务器作为守护进程运行。
2.2 bin/rails generate
bin/rails generate
命令使用模板来创建很多东西。单独运行 bin/rails generate
会显示可用生成器的列表。
您还可以使用别名“g”来调用生成器命令:bin/rails g
。
$ bin/rails generate
Usage:
bin/rails generate GENERATOR [args] [options]
...
...
Please choose a generator below.
Rails:
assets
channel
controller
generator
...
...
您可以通过生成器 gem、您肯定会安装的插件的一部分以及您自己创建的插件来安装更多生成器!
使用生成器将通过编写 **样板代码**(应用程序运行所必需的代码)来节省大量时间。
让我们使用控制器生成器创建自己的控制器。但是应该使用什么命令呢?让我们问问生成器。
所有 Rails 控制台实用程序都有帮助文本。与大多数 *nix 实用程序一样,您可以尝试在末尾添加 --help
或 -h
,例如 bin/rails server --help
。
$ bin/rails generate controller
Usage:
bin/rails generate controller NAME [action action] [options]
...
...
Description:
...
To create a controller within a module, specify the controller name as a path like 'parent_module/controller_name'.
...
Example:
`bin/rails generate controller CreditCards open debit credit close`
Credit card controller with URLs like /credit_cards/debit.
Controller: app/controllers/credit_cards_controller.rb
Test: test/controllers/credit_cards_controller_test.rb
Views: app/views/credit_cards/debit.html.erb [...]
Helper: app/helpers/credit_cards_helper.rb
控制器生成器期望以 generate controller ControllerName action1 action2
的形式接受参数。让我们创建一个名为 Greetings
的控制器,其操作为 **hello**,该操作将向我们说些好听的话。
$ bin/rails generate controller Greetings hello
create app/controllers/greetings_controller.rb
route get 'greetings/hello'
invoke erb
create app/views/greetings
create app/views/greetings/hello.html.erb
invoke test_unit
create test/controllers/greetings_controller_test.rb
invoke helper
create app/helpers/greetings_helper.rb
invoke test_unit
这些都生成了什么?它确保了我们的应用程序中存在许多目录,并创建了控制器文件、视图文件、功能测试文件、视图助手、JavaScript 文件和样式表文件。
查看控制器并稍微修改一下(在 app/controllers/greetings_controller.rb
中)。
class GreetingsController < ApplicationController
def hello
@message = "Hello, how are you today?"
end
end
然后是视图,用于显示我们的消息(在 app/views/greetings/hello.html.erb
中)。
<h1>A Greeting for You!</h1>
<p><%= @message %></p>
使用 bin/rails server
启动服务器。
$ bin/rails server
=> Booting Puma...
URL 将是 https://127.0.0.1:3000/greetings/hello。
在普通的 Rails 应用程序中,您的 URL 通常会遵循 http://(主机)/(控制器)/(操作) 的模式,而类似 http://(主机)/(控制器) 的 URL 会命中该控制器的 **index** 操作。
Rails 还带有一个用于数据模型的生成器。
$ bin/rails generate model
Usage:
bin/rails generate model NAME [field[:type][:index] field[:type][:index]] [options]
...
ActiveRecord options:
[--migration], [--no-migration] # Indicates when to generate migration
# Default: true
...
Description:
Generates a new model. Pass the model name, either CamelCased or
under_scored, and an optional list of attribute pairs as arguments.
...
有关 type
参数的可用字段类型的列表,请参阅 API 文档,了解 SchemaStatements
模块的 add_column 方法。index
参数会为该列生成相应的索引。
但是,与其直接生成模型(我们稍后会进行),不如先建立一个脚手架。在 Rails 中,脚手架包含模型、该模型的数据库迁移、用于操作模型的控制器、用于查看和操作数据的视图,以及对上述每个部分的测试套件。
我们将设置一个名为“HighScore”的简单资源,用于跟踪我们在玩视频游戏时获得的最高分数。
$ bin/rails generate scaffold HighScore game:string score:integer
invoke active_record
create db/migrate/20190416145729_create_high_scores.rb
create app/models/high_score.rb
invoke test_unit
create test/models/high_score_test.rb
create test/fixtures/high_scores.yml
invoke resource_route
route resources :high_scores
invoke scaffold_controller
create app/controllers/high_scores_controller.rb
invoke erb
create app/views/high_scores
create app/views/high_scores/index.html.erb
create app/views/high_scores/edit.html.erb
create app/views/high_scores/show.html.erb
create app/views/high_scores/new.html.erb
create app/views/high_scores/_form.html.erb
invoke test_unit
create test/controllers/high_scores_controller_test.rb
create test/system/high_scores_test.rb
invoke helper
create app/helpers/high_scores_helper.rb
invoke test_unit
invoke jbuilder
create app/views/high_scores/index.json.jbuilder
create app/views/high_scores/show.json.jbuilder
create app/views/high_scores/_high_score.json.jbuilder
生成器会为 HighScore 创建模型、视图、控制器、资源路由和数据库迁移(它会创建 high_scores
表),并为它们添加测试。
迁移要求我们进行迁移,即运行一些 Ruby 代码(来自上述输出的 20190416145729_create_high_scores.rb
文件)来修改数据库的模式。哪个数据库?当我们运行 bin/rails db:migrate
命令时,Rails 会为您创建的 SQLite3 数据库。我们将在下面详细介绍该命令。
$ bin/rails db:migrate
== CreateHighScores: migrating ===============================================
-- create_table(:high_scores)
-> 0.0017s
== CreateHighScores: migrated (0.0019s) ======================================
让我们谈谈单元测试。单元测试是用于测试和断言代码的代码。在单元测试中,我们会取一小段代码,比如模型中的一个方法,并测试其输入和输出。单元测试是您的朋友。您越早意识到单元测试代码会极大地提高您的生活质量,就越好。说真的。请访问 测试指南,深入了解单元测试。
让我们看看 Rails 为我们创建的界面。
$ bin/rails server
转到您的浏览器,打开 https://127.0.0.1:3000/high_scores,现在我们可以创建新的最高分数了(在 Space Invaders 上得了 55,160 分!)。
2.3 bin/rails console
console
命令允许您从命令行与 Rails 应用程序交互。在底层,bin/rails console
使用 IRB,因此如果您以前使用过它,您会立即上手。这对于用代码测试快速想法并在不触碰网站的情况下在服务器端更改数据很有用。
您也可以使用别名“c”来调用控制台:bin/rails c
。
您可以指定 console
命令应在其中运行的环境。
$ bin/rails console -e staging
如果您想测试一些代码而不更改任何数据,可以通过调用 bin/rails console --sandbox
来实现。
$ bin/rails console --sandbox
Loading development environment in sandbox (Rails 8.0.0)
Any modifications you make will be rolled back on exit
irb(main):001:0>
2.3.1 app
和 helper
对象
在 bin/rails console
中,您可以访问 app
和 helper
实例。
使用 app
方法,您可以访问命名路由助手,以及发出请求。
irb> app.root_path
=> "/"
irb> app.get _
Started GET "/" for 127.0.0.1 at 2014-06-19 10:41:57 -0300
...
使用 helper
方法,可以访问 Rails 和应用程序的助手。
irb> helper.time_ago_in_words 30.days.ago
=> "about 1 month"
irb> helper.my_custom_helper
=> "my custom helper"
2.4 bin/rails dbconsole
bin/rails dbconsole
会找出您正在使用的数据库,并将您带入您会用它使用的任何命令行界面(并找出要传递给它的命令行参数!)。它支持 MySQL(包括 MariaDB)、PostgreSQL 和 SQLite3。
您也可以使用别名“db”来调用 dbconsole:bin/rails db
。
如果您使用多个数据库,bin/rails dbconsole
默认情况下将连接到主数据库。您可以使用 --database
或 --db
指定要连接的数据库。
$ bin/rails dbconsole --database=animals
2.5 bin/rails runner
runner
在 Rails 应用程序的上下文中非交互地运行 Ruby 代码,无需打开 Rails console
。例如
$ bin/rails runner "Model.long_running_method"
您也可以使用别名“r”来调用 runner:bin/rails r
。
您可以使用 -e
开关指定 runner
命令应在其中运行的环境。
$ bin/rails runner -e staging "Model.long_running_method"
您甚至可以使用 runner 执行文件中编写的 ruby 代码。
$ bin/rails runner lib/code_to_be_run.rb
默认情况下,rails runner
脚本会自动使用 Rails 执行器包装,这有助于为 cron 作业等任务报告未捕获的异常。
因此,执行 rails runner lib/long_running_scripts.rb
在功能上等同于以下内容
Rails.application.executor.wrap do
# executes code inside lib/long_running_scripts.rb
end
您可以使用 --skip-executor
选项选择退出此行为。
$ bin/rails runner --skip-executor lib/long_running_script.rb
2.6 bin/rails destroy
可以将 destroy
视为 generate
的反面。它会找出生成器做了什么,并撤消它。
您也可以使用别名“d”来调用 destroy 命令:bin/rails d
。
$ bin/rails generate model Oops
invoke active_record
create db/migrate/20120528062523_create_oops.rb
create app/models/oops.rb
invoke test_unit
create test/models/oops_test.rb
create test/fixtures/oops.yml
$ bin/rails destroy model Oops
invoke active_record
remove db/migrate/20120528062523_create_oops.rb
remove app/models/oops.rb
invoke test_unit
remove test/models/oops_test.rb
remove test/fixtures/oops.yml
2.7 bin/rails about
bin/rails about
提供有关 Ruby、RubyGems、Rails、Rails 子组件、应用程序文件夹、当前 Rails 环境名称、应用程序的数据库适配器和模式版本的信息。当您需要寻求帮助、检查安全补丁是否会影响您或需要有关现有 Rails 安装的一些统计信息时,它很有用。
$ bin/rails about
About your application's environment
Rails version 8.0.0
Ruby version 3.2.0 (x86_64-linux)
RubyGems version 3.3.7
Rack version 3.0.8
JavaScript Runtime Node.js (V8)
Middleware: ActionDispatch::HostAuthorization, Rack::Sendfile, ActionDispatch::Static, ActionDispatch::Executor, ActionDispatch::ServerTiming, ActiveSupport::Cache::Strategy::LocalCache::Middleware, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, ActionDispatch::RemoteIp, Sprockets::Rails::QuietAssets, Rails::Rack::Logger, ActionDispatch::ShowExceptions, WebConsole::Middleware, ActionDispatch::DebugExceptions, ActionDispatch::ActionableExceptions, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::Migration::CheckPending, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ContentSecurityPolicy::Middleware, ActionDispatch::PermissionsPolicy::Middleware, Rack::Head, Rack::ConditionalGet, Rack::ETag, Rack::TempfileReaper
Application root /home/foobar/my_app
Environment development
Database adapter sqlite3
Database schema version 20180205173523
2.8 bin/rails assets:
您可以使用 bin/rails assets:precompile
预编译 app/assets
中的资产,并使用 bin/rails assets:clean
删除旧的已编译资产。assets:clean
命令允许进行滚动部署,这些部署可能仍在链接到旧资产,而新资产正在构建。
如果您想完全清除 public/assets
,可以使用 bin/rails assets:clobber
。
2.9 bin/rails db:
db:
rails 命名空间中最常见的命令是 migrate
和 create
,尝试所有迁移 rails 命令(up
、down
、redo
、reset
)将是有益的。bin/rails db:version
在故障排除时很有用,它会告诉您数据库的当前版本。
有关迁移的更多信息,请参阅 迁移 指南。
2.10 bin/rails notes
bin/rails notes
在您的代码中搜索以特定关键字开头的注释。您可以参考 bin/rails notes --help
以获取有关用法的更多信息。
默认情况下,它将在 app
、config
、db
、lib
和 test
目录中搜索具有 .builder
、.rb
、.rake
、.yml
、.yaml
、.ruby
、.css
、.js
和 .erb
扩展名的文件中以 FIXME、OPTIMIZE 和 TODO 注释。
$ bin/rails notes
app/controllers/admin/users_controller.rb:
* [ 20] [TODO] any other way to do this?
* [132] [FIXME] high priority for next deploy
lib/school.rb:
* [ 13] [OPTIMIZE] refactor this code to make it faster
* [ 17] [FIXME]
2.10.1 注释
您可以使用 --annotations
参数传递特定的注释。默认情况下,它将搜索 FIXME、OPTIMIZE 和 TODO。请注意,注释区分大小写。
$ bin/rails notes --annotations FIXME RELEASE
app/controllers/admin/users_controller.rb:
* [101] [RELEASE] We need to look at this before next release
* [132] [FIXME] high priority for next deploy
lib/school.rb:
* [ 17] [FIXME]
2.10.2 标签
您可以使用 config.annotations.register_tags
添加更多要搜索的默认标签。它接收一个标签列表。
config.annotations.register_tags("DEPRECATEME", "TESTME")
$ bin/rails notes
app/controllers/admin/users_controller.rb:
* [ 20] [TODO] do A/B testing on this
* [ 42] [TESTME] this needs more functional tests
* [132] [DEPRECATEME] ensure this method is deprecated in next release
2.10.3 目录
您可以使用 config.annotations.register_directories
添加更多要搜索的默认目录。它接收一个目录名称列表。
config.annotations.register_directories("spec", "vendor")
$ bin/rails notes
app/controllers/admin/users_controller.rb:
* [ 20] [TODO] any other way to do this?
* [132] [FIXME] high priority for next deploy
lib/school.rb:
* [ 13] [OPTIMIZE] Refactor this code to make it faster
* [ 17] [FIXME]
spec/models/user_spec.rb:
* [122] [TODO] Verify the user that has a subscription works
vendor/tools.rb:
* [ 56] [TODO] Get rid of this dependency
2.10.4 扩展
您可以使用 config.annotations.register_extensions
添加更多要搜索的默认文件扩展名。它接收一个扩展名列表及其对应的正则表达式以进行匹配。
config.annotations.register_extensions("scss", "sass") { |annotation| /\/\/\s*(#{annotation}):?\s*(.*)$/ }
$ bin/rails notes
app/controllers/admin/users_controller.rb:
* [ 20] [TODO] any other way to do this?
* [132] [FIXME] high priority for next deploy
app/assets/stylesheets/application.css.sass:
* [ 34] [TODO] Use pseudo element for this class
app/assets/stylesheets/application.css.scss:
* [ 1] [TODO] Split into multiple components
lib/school.rb:
* [ 13] [OPTIMIZE] Refactor this code to make it faster
* [ 17] [FIXME]
spec/models/user_spec.rb:
* [122] [TODO] Verify the user that has a subscription works
vendor/tools.rb:
* [ 56] [TODO] Get rid of this dependency
2.11 bin/rails routes
bin/rails routes
将列出您定义的所有路由,这对于跟踪应用程序中的路由问题或概述您正在尝试熟悉的应用程序中的 URL 很有用。
2.12 bin/rails test
对 Rails 中单元测试的良好描述见于 Rails 应用程序测试指南
Rails 自带一个名为 minitest 的测试框架。Rails 的稳定性归功于测试的使用。test:
命名空间中可用的命令有助于运行您希望编写的不同测试。
2.13 bin/rails tmp:
Rails.root/tmp
目录类似于 *nix /tmp 目录,是用于保存临时文件(如进程 ID 文件和缓存操作)的地方。
tmp:
命名空间命令将帮助您清除和创建 Rails.root/tmp
目录
bin/rails tmp:cache:clear
清除tmp/cache
。bin/rails tmp:sockets:clear
清除tmp/sockets
。bin/rails tmp:screenshots:clear
清除tmp/screenshots
。bin/rails tmp:clear
清除所有缓存、套接字和屏幕截图文件。bin/rails tmp:create
创建用于缓存、套接字和 pid 的 tmp 目录。
2.14 杂项
bin/rails initializers
打印出所有定义的初始化器,按 Rails 调用它们的顺序排列。bin/rails middleware
列出为您的应用程序启用的 Rack 中间件堆栈。bin/rails stats
非常适合查看代码的统计信息,显示 KLOC(千行代码)和代码测试比率等内容。bin/rails secret
将为您提供一个伪随机密钥,用于您的会话密钥。bin/rails time:zones:all
列出 Rails 知道的全部时区。bin/rails boot
启动应用程序并退出。
2.15 自定义 Rake 任务
自定义 rake 任务具有 .rake
扩展名,并放置在 Rails.root/lib/tasks
中。您可以使用 bin/rails generate task
命令创建这些自定义 rake 任务。
desc "I am short, but comprehensive description for my cool task"
task task_name: [:prerequisite_task, :another_task_we_depend_on] do
# All your magic here
# Any valid Ruby code is allowed
end
要将参数传递给自定义 rake 任务
task :task_name, [:arg_1] => [:prerequisite_1, :prerequisite_2] do |task, args|
argument_1 = args.arg_1
end
您可以通过将任务放在命名空间中来对任务进行分组
namespace :db do
desc "This task does nothing"
task :nothing do
# Seriously, nothing
end
end
调用任务将类似于
$ bin/rails task_name
$ bin/rails "task_name[value 1]" # entire argument string should be quoted
$ bin/rails "task_name[value 1,value2,value3]" # separate multiple args with a comma
$ bin/rails db:nothing
如果您需要与应用程序模型交互、执行数据库查询等等,您的任务应依赖于 environment
任务,该任务将加载您的应用程序代码。
task task_that_requires_app_code: [:environment] do
User.create!
end