分类: Ruby Ruby 软件工程师 编程语言
2019-08-21 12:55:51
Rails是一个用Ruby编写的Web应用程序框架。 它采用了一种固执的应用程序开发方法,假设集合约定最适合有共同目标的开发人员。 因此,Rails提供了处理路由,有状态数据,资产管理等的约定,以提供大多数Web应用程序所需的基线功能。
Rails遵循模型 - 视图 - 控制器 (MCV)架构模式,它将位于模型中的应用程序逻辑与应用程序信息的路由和表示分开。 这种组织结构 - 以及允许开发人员将代码提取到帮助程序和部分内容的其他约定 - 确保不会不必要地重复应用程序代码。
在本教程中,您将构建一个Rails应用程序,使用户能够发布有关鲨鱼及其行为的信息。 这将是未来应用程序开发的良好起点。
要学习本教程,您需要:
ufw
配置的防火墙。 有关如何进行此设置的说明,请参阅使用Ubuntu 18.04的初始服务器设置教程。 在创建我们的Rails shark应用程序之前,我们需要确保有一个用于存储用户数据的数据库。 Rails默认配置为使用SQLite ,这通常是开发中的一个不错的选择。 由于我们的应用程序数据不需要高级程序可扩展性,因此SQLite将满足我们的需求。
首先,更新包索引:
sudo apt update
接下来,安装sqlite3
和libsqlite3-dev
软件包:
sudo apt install sqlite3 libsqlite3-dev
这将安装SQLite及其所需的开发文件。
检查您的版本以确认安装是否成功:
sqlite3 --version
3.22.0 2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2alt1
安装SQLite后,您就可以开始开发应用程序了。
安装了我们的数据库后,我们可以创建一个新的Rails项目,并查看Rails为rails new
命令提供的一些默认样板代码。
使用以下命令创建名为sharkapp
的项目:
rails new sharkapp
您将看到大量输出,告诉您Rails为您的新项目创建的内容。 下面的输出突出显示了一些重要的文件,目录和命令:
create
. . .
create Gemfile
. . .
create app
. . .
create app/controllers/application_controller.rb
. . .
create app/models/application_record.rb
. . .
create app/views/layouts/application.html.erb
. . .
create config
create config/routes.rb
create config/application.rb
. . .
create config/environments
create config/environments/development.rb
create config/environments/production.rb
create config/environments/test.rb
. . .
create config/database.yml
create db
create db/seeds.rb
. . .
run bundle install
. . .
Bundle complete! 18 Gemfile dependencies, 78 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
. . .
* bin/rake: Spring inserted
* bin/rails: Spring inserted
此处突出显示的输出告诉您Rails创建了以下内容:
Gemfile
:此文件列出了应用程序的gem依赖项。 gem是一个Ruby软件包,Gemfile允许您管理项目的软件需求。 app
: app
目录是主应用程序代码所在的位置。 这包括构成应用程序本身的模型,控制器,视图,资产,帮助程序和邮件程序。 Rails为MCV模型提供了一些应用级样板,从app/models/application_record.rb
, app/controllers/application_controller.rb
和app/views/layouts/application.html.erb
。 config
:此目录包含应用程序的配置设置: config/routes.rb
:您的应用程序的路由声明存在于此文件中。 config/application.rb
:应用程序组件的常规设置位于此文件中。 config/environments
:此目录是环境的配置设置。 Rails默认包括三个环境: development
, production
和test
。 config/database.yml
:数据库配置设置存在于此文件中,该文件分为四个部分: default
, development
, production
和test
。 由于rails new
命令附带的Gemfile(包括sqlite3
gem),我们的config/database.yml
文件已将其adapter
参数设置为sqlite3
,指定我们将在此应用程序中使用SQLite数据库。 db
:此文件夹包含一个名为migrate
数据库迁移目录,以及schema.rb
和seeds.rb
文件。 schema.db
包含有关数据库的信息,而seeds.rb
是您可以为数据库放置种子数据的位置。 最后,Rails运行bundle install
命令来安装Gemfile
列出的依赖Gemfile
。
设置完所有内容后,导航到sharkapp
目录:
cd sharkapp
您现在可以使用rails server
命令启动Rails服务器以确保您的应用程序正常工作。 如果您正在使用本地计算机,请键入:
rails server
Rails默认绑定到localhost
,因此您现在可以通过将浏览器导航到locahost:3000
来访问您的应用程序,您将在其中看到以下图像:
如果您正在使用开发服务器,请首先确保端口3000
上允许连接:
sudo ufw allow 3000
然后使用--binding
标志启动服务器,以绑定到您的服务器IP:
rails server --binding=your_server_ip
在浏览器中导航到http:// your_server_ip :3000
,您将在其中看到Rails欢迎消息。
环顾四周后,您可以使用CTRL+C
停止服务器。
创建并准备好应用程序后,您就可以从Rails样板开始构建,以创建一个独特的应用程序。
要创建我们的鲨鱼信息应用程序,我们需要创建一个模型来管理我们的应用程序数据,视图以实现用户与该数据的交互,以及一个控制器来管理模型和视图之间的通信。 要构建这些东西,我们将使用rails generate scaffold
命令,它将为我们提供模型, 数据库迁移以更改数据库模式,控制器,管理创建,读取,更新和删除的全套视图(CRUD)应用程序的操作,以及部分,帮助程序和测试的模板。
因为generate scaffold
命令为我们做了很多工作,我们将仔细研究它创建的资源,以了解Rails正在做的工作。
我们的generate scaffold
命令将包括我们的模型名称和我们在数据库表中需要的字段。 Rails使用Active Record来管理应用程序数据(构建为具有模型的对象)和应用程序数据库之间的关系。 我们的每个模型都是Ruby类 ,同时也继承自ActiveRecord::Base
类。 这意味着我们可以使用与使用Ruby类相同的方式处理模型类,同时还可以从Active Record中提取方法。 然后,Active Record将确保将每个类映射到数据库中的表,并将该类的每个实例映射到该表中的一行。
键入以下命令以生成Shark
模型,控制器和关联的视图:
rails generate scaffold Shark name:string facts:text
使用name:string
和facts:text
我们给出Rails有关我们希望在数据库表中使用的字段以及它们应该接受的数据类型的信息。 两者都会为我们输入我们想要的内容提供空间,尽管text
将允许更多的角色来获取鲨鱼事实。
当您键入此命令时,您将再次看到一个很长的输出列表,它解释了Rails为您生成的所有内容。 下面的输出突出显示了我们设置的一些更重要的事情:
invoke active_record
create db/migrate/20190804181822_create_sharks.rb
create app/models/shark.rb
. . .
invoke resource_route
route resources :sharks
invoke scaffold_controller
create app/controllers/sharks_controller.rb
invoke erb
create app/views/sharks
create app/views/sharks/index.html.erb
create app/views/sharks/edit.html.erb
create app/views/sharks/show.html.erb
create app/views/sharks/new.html.erb
create app/views/sharks/_form.html.erb
. . .
Rails已经在app/models/shark.rb
创建了模型,并进行了数据库迁移: db/migrate/ 20190804181822 _create_sharks.rb
。 迁移文件的时间戳与您在此处看到的时间戳不同。
它还创建了一个控制器app/controllers/sharks_controller.rb
,以及与app/views/sharks
下收集的应用程序的CRUD操作相关的app/views/sharks
。 这些视图中有一个部分的_form.html.erb
,其中包含跨视图使用的代码。
最后,Rails添加了一条新的资源丰富的路由, resources :sharks
, config/routes.rb
。 这使Rails路由器能够将传入的HTTP请求与sharks
控制器及其相关视图进行匹配。
虽然Rails已经完成了为我们构建应用程序代码的大部分工作,但值得一看有些文件来了解正在发生的事情。
首先,让我们使用以下命令查看控制器文件:
cat app/controllers/sharks_controller.rb
class SharksController < ApplicationController
before_action :set_shark, only: [:show, :edit, :update, :destroy]
# GET /sharks
# GET /sharks.json
def index
@sharks = Shark.all
end
# GET /sharks/1
# GET /sharks/1.json
def show
end
# GET /sharks/new
def new
@shark = Shark.new
end
# GET /sharks/1/edit
def edit
end
# POST /sharks
# POST /sharks.json
def create
@shark = Shark.new(shark_params)
respond_to do |format|
if @shark.save
format.html { redirect_to @shark, notice: 'Shark was successfully created.' }
format.json { render :show, status: :created, location: @shark }
else
format.html { render :new }
format.json { render json: @shark.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /sharks/1
# PATCH/PUT /sharks/1.json
def update
respond_to do |format|
if @shark.update(shark_params)
format.html { redirect_to @shark, notice: 'Shark was successfully updated.' }
format.json { render :show, status: :ok, location: @shark }
else
format.html { render :edit }
format.json { render json: @shark.errors, status: :unprocessable_entity }
end
end
end
# DELETE /sharks/1
# DELETE /sharks/1.json
def destroy
@shark.destroy
respond_to do |format|
format.html { redirect_to sharks_url, notice: 'Shark was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_shark
@shark = Shark.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def shark_params
params.require(:shark).permit(:name, :facts)
end
end
控制器负责管理如何获取信息并将其传递给其关联模型,以及它如何与特定视图相关联。 如您所见,我们的sharks
控制器包含一系列方法,大致映射到标准CRUD操作。 但是,有比CRUD功能更多的方法,以便在出现错误时提高效率。
例如,考虑create
方法:
. . .
def create
@shark = Shark.new(shark_params)
respond_to do |format|
if @shark.save
format.html { redirect_to @shark, notice: 'Shark was successfully created.' }
format.json { render :show, status: :created, location: @shark }
else
format.html { render :new }
format.json { render json: @shark.errors, status: :unprocessable_entity }
end
end
end
. . .
如果成功保存了Shark
类的新实例, redirect_to
将生成一个新请求,然后将该请求定向到控制器。 这将是一个GET
请求,它将由show
方法处理,该方法将向用户显示他们刚刚添加的鲨鱼。
如果出现故障,则Rails将再次呈现app/views/sharks/new.html.erb
模板,而不是向路由器发出另一个请求,从而为用户提供另一个提交数据的机会。
除了鲨鱼控制器之外,Rails还为我们提供了index
视图的模板,该模板映射到控制器中的index
方法。 我们将使用它作为我们应用程序的根视图,因此值得一看。
键入以下内容以输出文件:
cat app/views/sharks/index.html.erb
<p id="notice"><%= notice %></p>
<h1>Sharks</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Facts</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @sharks.each do |shark| %>
<tr>
<td><%= shark.name %></td>
<td><%= shark.facts %></td>
<td><%= link_to 'Show', shark %></td>
<td><%= link_to 'Edit', edit_shark_path(shark) %></td>
<td><%= link_to 'Destroy', shark, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Shark', new_shark_path %>
index
视图遍历我们的Shark
类的实例,这些实例已映射到数据库中的sharks
表。 使用ERB模板 ,视图输出与单个shark实例关联的表中的每个字段: name
和facts
。
然后,视图使用link_to
帮助程序创建超链接,提供的字符串作为链接的文本,提供的路径作为目标。 当我们使用rails generate scaffold
命令定义sharks
资源路径时,通过我们可用的帮助程序可以实现路径本身。
除了查看我们的index
视图外,我们还可以查看new
视图以了解Rails如何在视图中使用partial。 键入以下内容以输出app/views/sharks/new.html.erb
模板:
cat app/views/sharks/new.html.erb
<h1>New Shark</h1>
<%= render 'form', shark: @shark %>
<%= link_to 'Back', sharks_path %>
虽然此模板可能看起来缺少新鲨鱼条目的输入字段,但render 'form'
的引用告诉我们模板正在拉入_form.html.erb
部分,该部分提取跨视图重复的代码。
查看该文件将让我们充分了解如何创建新的shark实例:
cat app/views/sharks/_form.html.erb
<%= form_with(model: shark, local: true) do |form| %>
<% if shark.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(shark.errors.count, "error") %> prohibited this shark from being saved:</h2>
<ul>
<% shark.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name %>
</div>
<div class="field">
<%= form.label :facts %>
<%= form.text_area :facts %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
此模板使用form_with
表单帮助程序 。 表单助手旨在使用特定模型的字段和范围从用户输入中创建新对象。 这里, form_with
将model: shark
作为参数,并且它创建的新表单构建器对象具有与sharks
表中的字段对应的字段输入。 因此,用户具有表单字段以输入鲨鱼name
和鲨鱼facts
。
提交此表单将创建一个JSON响应,其中包含应用程序的其余部分可以通过params方法访问的用户数据,该方法使用该数据创建ActionController::Parameters
对象。
既然您已经了解了rails generate scaffold
,您可以继续设置应用程序的根视图。
理想情况下,您希望应用程序的登录页面映射到应用程序的根目录,以便用户可以立即了解应用程序的用途。
您可以通过多种方式处理此问题:例如,您可以创建一个Welcome
控制器和一个关联的index
视图,这将为用户提供一个通用登录页面,该页面也可以链接到应用程序的不同部分。 然而,在我们的案例中,让用户登陆我们的index
鲨鱼视图将足以介绍该应用程序的目的。
要进行此设置,您需要修改config/routes.rb
的路由设置以指定应用程序的根目录。
使用nano
或您喜欢的编辑器打开config/routes.rb
进行编辑:
nano config/routes.rb
该文件将如下所示:
Rails.application.routes.draw do
resources :sharks
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
如果不设置更具体的内容, http://localhost:3000
或http:// your_server_ip :3000
的默认视图将成为默认的Rails欢迎页面。
为了将应用程序的根视图映射到sharks控制器的index
视图,您需要将以下行添加到文件中:
Rails.application.routes.draw do
resources :sharks
root 'sharks#index'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
现在,当用户导航到您的应用程序根目录时,他们将看到完整的鲨鱼列表,并有机会创建新的鲨鱼条目,查看现有条目,以及编辑或删除给定条目。
完成编辑后,保存文件并退出编辑器。 如果您使用nano
编辑文件,可以按CTRL+X
, Y
,然后按ENTER
您现在可以使用以下命令运行迁移:
rails db:migrate
您将看到确认迁移的输出。
再次启动Rails服务器。 如果您在本地工作,请键入:
rails s
在开发服务器上,键入:
rails s --binding=your_server_ip
如果您在本地工作,则导航到localhost:3000
如果您正在使用开发服务器,则导航到http:// your_server_ip :3000
。
您的应用程序登录页面如下所示:
要创建新的鲨鱼,请单击页面底部的New Shark链接,它将带您进入sharks/new
路线:
让我们添加一些演示信息来测试我们的应用程序。 在“ 名称”字段中输入“Great White”,在“ Facts”字段中输入“Scary”:
单击“ 创建”按钮以创建鲨鱼。
这将引导您进入show
route,由于before_action
过滤器,使用set_shark
方法设置,该方法获取我们刚刚创建的鲨鱼的id
:
class SharksController < ApplicationController
before_action :set_shark, only: [:show, :edit, :update, :destroy]
. . .
def show
end
. . .
private
# Use callbacks to share common setup or constraints between actions.
def set_shark
@shark = Shark.find(params[:id])
end
. . .
您可以通过单击鲨鱼条目上的编辑来立即测试编辑功能。 这将带您进入该鲨鱼的edit
路线:
将有关Great White的facts
更改为“Large”而不是“Scary”,然后单击Update Shark 。 这将带您回到show
路线:
最后,单击Back将转到更新的index
视图:
现在您已经测试了应用程序的基本功能,您可以添加一些验证和安全检查,以使一切更安全。
您的鲨鱼应用程序可以接受来自用户的输入,但想象一下用户尝试创建鲨鱼而不向其添加事实的情况,或者为已经在数据库中的鲨鱼创建条目。 您可以通过向模型添加验证来创建在将数据输入数据库之前检查数据的机制。 由于应用程序的逻辑位于其模型中,因此在此处验证数据输入比在应用程序中的其他位置更有意义。
请注意,我们不会在本教程中介绍编写验证测试,但您可以通过查阅Rails文档了解有关测试的更多信息。
如果您还没有停止服务器,请输入CTRL+C
。
打开shark.rb
模型文件:
nano app/models/shark.rb
目前,该文件告诉我们Shark
类继承自ApplicationRecord
,而ApplicationRecord
继承自ActiveRecord::Base
:
class Shark < ApplicationRecord
end
让我们首先在我们的name
字段中添加一些验证,以确认该字段已填写并且该条目是唯一的,从而防止重复条目:
class Shark < ApplicationRecord
validates :name, presence: true, uniqueness: true
end
接下来,为facts
字段添加验证,以确保它也被填写:
class Shark < ApplicationRecord
validates :name, presence: true, uniqueness: true
validates :facts, presence: true
end
我们不太关心事实的独特性,只要它们与独特的鲨鱼条目相关联。
完成后保存并关闭文件。
使用rails s
或rails s --binding= your_server_ip
再次启动服务器,具体取决于您是在本地工作还是使用开发服务器。
导航到应用程序的根目录为http://localhost:3000
或http:// your_server_ip :3000
。
点击New Shark 。 在表单中,将“Great White”添加到Name字段,将“Big Teeth”添加到Facts字段,然后单击Create Shark 。 您应该看到以下警告:
现在,让我们看看我们是否可以检查其他验证。 单击“ 返回”返回主页,然后再次返回“ 新鲨鱼” 。 在新表单中,在“ 名称”字段中输入“Tiger Shark”,并将Facts留空。 单击Create Shark将触发以下警告:
通过这些更改,您的应用程序可以进行一些验证,以确保保存到数据库的数据的一致性。 现在,您可以将注意力转移到应用程序的用户身上,并定义谁可以修改应用程序数据。
通过验证,我们可以保证将数据保存到数据库中。 但是用户怎么样? 如果我们不希望任何和所有用户都添加到数据库,那么我们应该添加一些身份验证措施,以确保只有允许的用户才能添加鲨鱼。 为此,我们将使用http_basic_authenticate_with
方法 ,这将允许我们创建用户名和密码组合来验证用户。
有许多方法可以使用Rails对用户进行身份验证,包括使用bcrypt
或devise
gems。 但是,现在,我们将向应用程序控制器添加一个方法,该方法将应用于整个应用程序中的操作。 如果我们将来向应用程序添加更多控制器,这将非常有用。
使用CTRL+C
再次停止服务器。
打开定义ApplicationController
的文件:
nano app/controllers/application_controller.rb
在里面,您将看到ApplicationController
类的定义, ApplicationController
中的其他控制器继承该定义:
class ApplicationController < ActionController::Base
end
要对用户进行身份验证,我们将使用带有http_basic_authenticate_with
方法的硬编码用户名和密码。 将以下代码添加到文件中:
class ApplicationController < ActionController::Base
http_basic_authenticate_with name: 'sammy', password: 'shark', except: [:index, :show]
end
除了在这里提供用户名和密码之外,我们还通过指定不需要的路由来限制身份验证: index
和show
。 实现这一目标的另一种方法是only: [:create, :update, :destroy]
写only: [:create, :update, :destroy]
。 这样,所有用户都可以查看所有鲨鱼并阅读有关特定鲨鱼的事实。 但是,在修改网站内容时,用户需要证明他们有权访问。
在更健壮的设置中,您不希望以这种方式对值进行硬编码,但出于演示的目的,这将允许您了解如何为应用程序的路由包含身份验证。 它还允许您查看Rails默认情况下如何在Cookie中存储会话数据:一旦您对指定的操作进行身份验证,您将不需要在同一会话中再次进行身份验证。
完成编辑后,保存并关闭app/controllers/application_controller.rb
。 您现在可以测试身份验证。
使用rails s
或rails s --binding= your_server_ip
启动服务器,然后通过http://localhost:3000
或http:// your_server_ip :3000
导航到您的应用程序。
在登录页面上,单击New Shark按钮。 这将触发以下身份验证窗口:
如果输入您添加到app/controllers/application_controller.rb
的用户名和密码组合,您将能够安全地创建新的鲨鱼。
您现在有一个工作鲨鱼应用程序,完成数据验证和基本身份验证方案。
您在本教程中创建的Rails应用程序是一个可以用于进一步开发的跳出点。 如果您有兴趣探索Rails生态系统, 项目文档是一个很好的起点。
此外,您可能希望探索如何使用React等框架为项目设置更强大的前端。 如何使用React前端设置Ruby on Rails项目提供了有关如何执行此操作的指导。
如果您想探索不同的数据库选项,您还可以在Ubuntu 18.04上查看如何在Ruby on Rails应用程序中使用PostgreSQL ,该应用程序将介绍如何使用PostgreSQL而不是SQLite。 您还可以查阅我们的PostgreSQL教程库,以了解有关使用此数据库的更多信息。
关注云架构公众号
Linux入门
QQ交流群:308781113