Rails学习笔记之Rails 基础教程

resource ,资源。一个资源就是一种相似对象的集合,比如文章,用户。你可以对资源执行创建,读取,更新,删除的动作,这些动作被称为 CRUD 操作。

一个博客,里面可能会有文章资源。创建一个文章资源,名字是 articles,先添加一个资源类型的路由。编辑 config/routes.rb,添加一行 resources :articles,像这样:

Rails.application.routes.draw do
  resources :articles
  # ...
end
执行:

rails routes
返回:

       Prefix Verb   URI Pattern                  Controller#Action
     articles GET    /articles(.:format)          articles#index
              POST   /articles(.:format)          articles#create
  new_article GET    /articles/new(.:format)      articles#new
 edit_article GET    /articles/:id/edit(.:format) articles#edit
      article GET    /articles/:id(.:format)      articles#show
              PATCH  /articles/:id(.:format)      articles#update
              PUT    /articles/:id(.:format)      articles#update
              DELETE /articles/:id(.:format)      articles#destroy
welcome_index GET    /welcome/index(.:format)     welcome#index
         root GET    /                            welcome#index
new

访问一下:

http://localhost:3000/articles/new
会提示:

Routing Error
uninitialized constant ArticlesController
999C9C92-38E3-4E06-BAE6-EC36BA26A3A1

创建一个控制器:

rails generate controller Articles
返回:

Running via Spring preloader in process 217
      create  app/controllers/articles_controller.rb
      invoke  erb
      create    app/views/articles
      invoke  test_unit
      create    test/controllers/articles_controller_test.rb
      invoke  helper
      create    app/helpers/articles_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/articles.coffee
      invoke    scss
      create      app/assets/stylesheets/articles.scss
打开文件:

app/controllers/articles_controller.rb
里面的内容是:

class ArticlesController < ApplicationController
end
一个控制器就是一个类,继承了 ApplicationController 类。在这个类里定义的方法会变成控制器的动作,这些动作执行的就是 CRUD 操作。

刷新之前出错的页面,会提示:

Unknown action

The action 'new' could not be found for ArticlesController
意思是 Rails 在 ArticlesController 这个控制器里找不到 new 这个动作。我们可以手工的在这个控制器里添加一个 new 方法:

class ArticlesController < ApplicationController
  def new
  end
end
刷新,又会提示:

ActionController::UnknownFormat in ArticlesController#new

ArticlesController#new is missing a template for this request format and variant. request.formats: ["text/html"] request.variant: [] NOTE! For XHR/Ajax or API requests, this action would normally respond with 204 No Content: an empty white screen. Since you're loading it in a web browser, we assume that you expected to actually render a template, not… nothing, so we're showing an error to be extra-clear. If you expect 204 No Content, carry on. That's what you'll get from an XHR or API request. Give it a shot.
没找到跟控制器动作对应的视图。创建一个视图文件,位置是:

app/views/articles/new.html.erb
文件里的内容,输入:

<h1>添加新文章</h1>
刷新页面,页面上会出现 “添加新文章” 这几个字儿。

表单

用 form builder 在模板里面创建表单,用一下 form_for 方法,在 new.html.erb 文件里添加下面代码:

<%= form_for :article, url: articles_path do |f| %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>
<% end %>
把 :article 交给 form_for 方法,告诉 form_for 这是为谁做的表单。在方法的代码块里,FormBuilder 对象是用 f 表示的。用它创建了两个 label 标签,一个 text 文本框,一个 text_area 文件区域,还有一个 submit 提交按钮。url 选项设置了表单的 action 属性的值,articles_path 相当于 articles#create 动作。

点击表单的 save 按钮,会报错:

Unknown action
The action 'create' could not be found for ArticlesController
create

继续编辑 articles 控制器:

class ArticlesController < ApplicationController
  def new
  end

  def create
  end
end
添加了一个 create 方法,再次刷新页面。没有反应,因为我们没有指定要响应的东西,所以 Rails 默认会响应 204 No Content 。改造一下 create 方法:

  def create
    render plain: params[:article].inspect
  end
给 render 方法一个 hash,key 是 :plain,value 是 params[:article].inspect。params 表示的是表单里的参数(或字段),它返回的是一个 ActionController::Parameters 对象。

刷新,在表单里输入点内容,然后再点一下 Save Article 按钮,这次会返回:

<ActionController::Parameters {"title"=>"第一篇文章", "text"=>"这是文章的内容"} permitted: false>
Article 模型

Rails 里的模型使用单数名字,对应的数据库表用的是复数名字。

创建一个 Article 模型,title 是字符串类型,text 是文本类型,执行:

rails generate model Article title:string text:text
返回:

Running via Spring preloader in process 225
      invoke  active_record
      create    db/migrate/20160918102316_create_articles.rb
      create    app/models/article.rb
      invoke    test_unit
      create      test/models/article_test.rb
      create      test/fixtures/articles.yml
运行 migration

打开之前创建的 migration 文件,位置:db/migrate/YYYYMMDDHHMMSS_create_articles.rb,里面的内容是:

class CreateArticles < ActiveRecord::Migration[5.0]
  def change
    create_table :articles do |t|
      t.string :title
      t.text :text

      t.timestamps
    end
  end
end
运行 migration:

rails db:migrate
返回:

== 20160918102316 CreateArticles: migrating ===================================
-- create_table(:articles)
   -> 0.0166s
== 20160918102316 CreateArticles: migrated (0.0173s) ==========================

save

打开文件:

app/controllers/articles_controller.rb
把里面定义的 create 方法编辑成这样:

def create
  @article = Article.new(params[:article])

  @article.save
  redirect_to @article
end
打开地址:

http://localhost:3000/articles/new
试着发布一篇新文章,你会看到错误:

ActiveModel::ForbiddenAttributesError in ArticlesController#create

ActiveModel::ForbiddenAttributesError
这是为了安全报的错,strong parameters,我们需要告诉  Rails 允许哪些参数进入到控制器动作里。允许一下 title 与 text,使用 require 与 permit,改造一下 create 方法:

@article = Article.new(params.require(:article).permit(:title, :text))
也可以这样改造 create 方法:

def create
  @article = Article.new(article_params)

  @article.save
  redirect_to @article
end

private

def article_params
  params.require(:article).permit(:title, :text)
end
在发布新文章的页面上,在表单里输入点东西,提交。这次又会出现:

Unknown action

The action 'show' could not be found for ArticlesController
show

打开文件:

app/controllers/articles_controller.rb
定义 show 方法:

def show
  @article = Article.find(params[:id])
end
用 Article.find 找到请求的文章,交给 @article,Rails 会把所有的实例变量传递给视图。

创建视图文件:

app/views/articles/show.html.erb
内容:

<p>
  <strong>Title: </strong>
  <%= @article.title %>
</p>

<p>
  <strong>Text: </strong>
  <%= @article.text %>
</p>
再去创建一篇文章,打开地址:

http://localhost:3000/articles/new
B24397F6-B354-4319-8493-E723F2341ED4

index

打开文件:

app/controllers/articles_controller.rb
定义 index 方法:

def index
  @articles = Article.all
end
创建视图文件:

app/views/articles/index.html.erb
内容:

<h1>文章列表</h1>

<ul>
  <% @articles.each do |article| %>
    <li>
      <p>
        <strong>Title: </strong>
        <%= article.title %>
      </p>

      <p>
        <strong>Text: </strong>
        <%= article.text %>
      </p>

      <p>
        <%= link_to 'show', article_path(article) %>
      </p>
    </li>
  <% end %>
</ul>

打开地址:

http://localhost:3000/articles
4365F51E-C426-4BAB-B685-B510750AE9EC

link_to

打开文件:

app/views/welcome/index.html.erb
修改成:

<h1>hello</h1>
<%= link_to '我的博客', controller: 'articles' %>
link_to 是一个视图 helper。上面创建了一个链接是 “我的博客”,打开的地址是文章列表。

打开文件:

app/views/articles/index.html.erb
添加一个新建文章的链接:

<%= link_to '新建文章', new_article_path %>
打开文件:

app/views/articles/new.html.erb
添加一个文章列表的链接:

<%= link_to '返回', articles_path %>
打开文件:

app/views/articles/show.html.erb
添加一个文章列表的链接:

<%= link_to '返回', articles_path %>
验证

打开文件:

app/models/article.rb
编辑成:

class Article < ApplicationRecord
  validates :title, presence: true, length: { minimum: 5 }
end
上面验证的是 title,它的长度至少是 5 个字符。

打开文件:

app/controllers/articles_controller.rb
把 new 与 create 方法,修改成:

  def new
    @article = Article.new
  end

  def create
    @article = Article.new(article_params)

    if @article.save
      redirect_to @article
    else
      render 'new'
    end
  end
打开地址:

http://localhost:3000/articles/new
输入的标题小于 5 个字符,然后提交表单,你会发现,会返回到新建文章的页面,并且之前在表单里输入的东西仍然会存在。

再显示点错误的提示,打开文件:

app/views/articles/new.html.erb
像这样改造一下表单:

<%= form_for :article, url: articles_path do |f| %>
  <% if @article.errors.any? %>
  <div id ="error_explanation">
    <h2>
      <%= pluralize(@article.errors.count, "个错误") %>
    </h2>
    <ul>
      <% @article.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
      <% end %>
    </ul>
  </div>
 <% end %>
...
这次发布文章的时候,少输入几个字儿,会在页面上显示错误。

593FE234-62F2-4239-8B36-E97DE04625B0

edit

打开文件:

app/controllers/articles_controller.rb
添加一个 edit 方法:

def edit
  @article = Article.find(params[:id])
end
创建新文件:

app/views/articles/edit.html.erb
内容可以这样:

<h1>编辑文章</h1>
<%= form_for :article, url: article_path(@article), method: :patch do |f| %>
  <% if @article.errors.any? %>
  <div id ="error_explanation">
    <h2>
      <%= pluralize(@article.errors.count, "个错误") %>
    </h2>
    <ul>
      <% @article.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
      <% end %>
    </ul>
  </div>
  <% end %>

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

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>
<% end %>

<%= link_to '返回', articles_path %>
这回我们把表单的动作指向了 update 动作,这个动作还没有定义。

update

打开文件:

app/controllers/articles_controller.rb
添加一个 update 方法:

def update
  @article = Article.find(params[:id])

  if @article.update(article_params)
    redirect_to @article
  else
    render 'edit'
  end
end
打开文件:

app/views/articles/index.html.erb
在 show 的下面添加一个编辑按钮:

 <p>
   <%= link_to 'show', article_path(article) %>
   <%= link_to 'edit', edit_article_path(article) %>
 </p>
打开文件:

app/views/articles/show.html.erb
也添加一个编辑按钮:

<%= link_to '返回', articles_path %>
<%= link_to 'edit', edit_article_path(@article) %>
partials

文章的编辑页面与新建文章页面很像,它们都使用了一样的代码来显示表单。使用视图 partial 可以去掉重复。partial 文件名有一个下划线前缀。

创建新文件:

app/views/articles/_form.html.erb
文件里的内容:

<%= form_for @article do |f| %>
  <% if @article.errors.any? %>
  <div id ="error_explanation">
    <h2>
      <%= pluralize(@article.errors.count, "个错误") %>
    </h2>
    <ul>
      <% @article.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
      <% end %>
    </ul>
  </div>
  <% end %>

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

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>
<% end %>
@article 是一个资源,它对应一整套 RESTful 路由。Rails 知道自己应该使用哪个地址与方法。

更新文件:

app/views/articles/new.html.erb
内容:

<h1>添加新文章</h1>

<%= render 'form' %>

<%= link_to '返回', articles_path %>
更新文件:

app/views/articles/edit.html.erb
内容:

<h1>编辑文章</h1>

<%= render 'form' %>

<%= link_to '返回', articles_path %>
destroy

用 destroy 方法删除资源。

打开文件:

app/controllers/articles_controller.rb
添加 destroy 方法:

def destroy
  @article = Article.find(params[:id])
  @article.destroy

  redirect_to articles_path
end
打开文件:

app/views/articles/index.html.erb
在模板里添加删除按钮:

 <p>
   <%= link_to 'show', article_path(article) %>
   <%= link_to 'edit', edit_article_path(article) %>
   <%= link_to 'delete', article_path(article),
       method: :delete,
       data: { confirm: 'are you sure?' } %>
 </p>
2BF07671-D5FD-4D24-9EF0-A03F9B9BA913

第二个模型

再添加一个处理文章评论的模型。

生成模型

rails generate model Comment commenter:string body:text article:references
返回:

Running via Spring preloader in process 48
      invoke  active_record
      create    db/migrate/20160918190201_create_comments.rb
      create    app/models/comment.rb
      invoke    test_unit
      create      test/models/comment_test.rb
      create      test/fixtures/comments.yml
打开文件:

app/models/comment.rb
里面的内容是:

class Comment < ApplicationRecord
  belongs_to :article
end
比我们之前创建的 Article 模型多出一个 belongs_to :article ,这里设置的是 Active Record 关联。

执行 migration:

rails db:migrate
关联模型

Active Record 的关联可以声明两个模型之间的关系。这里就是评论与文章:

每个评论都属于一篇文章
一篇文章可以有多条评论
打开文件:

app/models/article.rb
添加一行代码:

  has_many :comments
整体的样子是:

class Article < ApplicationRecord
  has_many :comments
  validates :title, presence: true, length: { minimum: 5 }
end
为评论添加路由

打开文件:

config/routes.rb
像这样编辑:

 resources :articles do
   resources :comments
 end
这里给 articles 添加了一个嵌套的资源。

生成控制器

rails generate controller Comments
返回:

Running via Spring preloader in process 65
      create  app/controllers/comments_controller.rb
      invoke  erb
      create    app/views/comments
      invoke  test_unit
      create    test/controllers/comments_controller_test.rb
      invoke  helper
      create    app/helpers/comments_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/comments.coffee
      invoke    scss
      create      app/assets/stylesheets/comments.scss
打开文件:

app/controllers/comments_controller.rb
编辑内容:

class CommentsController < ApplicationController
  def create
    @article = Article.find(params[:article_id])
    @comment = @article.comments.create(comment_params)
    redirect_to article_path(@article)
  end

  private
    def comment_params
      params.require(:comment).permit(:commenter, :body)
    end
end
评论视图

打开文件:

app/views/articles/show.html.erb
添加评论的表示与评论用的表单:

<h2>评论</h2>
<% @article.comments.each do |comment| %>
  <p>
    <strong>评论者:</strong>
    <%= comment.commenter %>
  </p>

  <p>
    <strong>评论:</strong>
    <%= comment.body %>
  </p>
<% end %>

<h2>添加评论</h2>
<%= form_for([@article, @article.comments.build]) do |f| %>
  <p>
    <%= f.label :commenter %><br>
    <%= f.text_field :commenter %>
  </p>
  <p>
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
AD07E77C-C4ED-44BF-B189-6EEA5E5D18C3

Refactoring

创建文件:

app/views/comments/_comment.html.erb
文件里的内容:

  <p>
    <strong>评论者:</strong>
    <%= comment.commenter %>
  </p>

  <p>
    <strong>评论:</strong>
    <%= comment.body %>
  </p>
打开文件:

app/views/articles/show.html.erb
修改显示评论用的代码:

<h2>评论</h2>
<%= render @article.comments %>
render 会迭代 @article.comments。

创建文件:

app/views/comments/_form.html.erb
文件里的内容:

<%= form_for([@article, @article.comments.build]) do |f| %>
  <p>
    <%= f.label :commenter %><br>
    <%= f.text_field :commenter %>
  </p>
  <p>
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
打开文件:

app/views/articles/show.html.erb
修改评论表单:

删除评论

打开文件:

app/views/comments/_comment.html.erb
添加一个删除链接:

<p>
  <%= link_to 'delete comment', [comment.article, comment],
      method: :delete,
      data: { confirm: 'are you sure?' } %>
</p>
点击 delete comment,会执行 DELETE /articles/:article_id/comments/:id 。

打开文件:

app/controllers/comments_controller.rb
添加一个 destroy 方法:

def destroy
  @article = Article.find(params[:article_id])
  @comment = @article.comments.find(params[:id])
  @comment.destroy
  redirect_to article_path(@article)
end
删除相关对象

删除文章,同时也删除掉属于这篇文章的评论。

打开文件:

app/models/article.rb
编辑一下 has_many 那行代码:

has_many :comments, dependent: :destroy

时间: 2024-09-20 01:08:40

Rails学习笔记之Rails 基础教程的相关文章

rails学习笔记: rake db 相关命令

rails学习笔记: rake db 命令行 rake db:***** script/generate model task name:string priority:integer script/generate migration add_description_to_task description:string script/generate migration remove_description_from_task description:string 数据类型 引用 # :str

Ruby On Rails学习笔记(1)——安装Instant Rails

       Instans Rails是一个ROR的一个一站式解决方案,其中包含了Ruby.Rails.Apache和MySQL,并且所有都已经配置完成,可以直接运行.下面是在Windows XP安装和启动Instant Rails的过程.       1.下载Instant Rails,下载地址为:http://rubyforge.org/frs/?group_id=904,当前最新的Release版本为1.7,即InstantRails-1.7-win.zip:       2.将Inst

JavaScript高级程序设计(第3版)学习笔记 概述_基础知识

在JavaScript面世之初,没有人会想到它会被应用的如此广泛,也远比一般人想象中的要复杂强大的多,在我自己学习的过程中,曾经有过多次震撼,只是常常没有过多久,很多美轮美奂的用法就又模糊起来,希望通过对JavaScript高级程序设计(第3版)的专题学习笔记,能够较为系统的将基础知识梳理一次,也能够将自己平常学习与工作过程中遇到的一些美妙用法记录下来,便于自己再次学习,当然,也希望可以给有需要的朋友们一些力所能及的帮助. 相关术语 先简要说一下和JavaScript相关的一些背景术语,就不详细

JavaScript学习笔记之DOM基础 2.4_javascript技巧

DOM的发展,与WEB标准化的大趋势相关甚密.只有基于正确的语义逻辑,DOM才能正确地发挥其功用.如今,正确的语义结构.表现与内容分离等要求,都已经成为网页设计中的基本要求.因此,在网页前端开发中,DOM的存在,无疑是为表现层.行为层甚至内容层面的连接提供了一个绝佳的API,成为热门的Ajax应用中不可或缺的组成部分. 一.平稳退化 1.概念 早期,在未使用JavaScript之前,网页中的内容可以正常显示出来,用户可以通过外设(如鼠标)操控浏览到相关内容,这种浏览体验对用户而言可能并不理想.

Ruby On Rails学习笔记(2)——Convention over Configuration(ROR应用程序的目录结构)

        XML形式的配置文件是Web开发中最常见的文件,如web.xml.applicationContext.xml.*.hbm.xml等等,这些文件在为应用程序提供强大的灵活性的同时也大大增加配置的复杂度.而Rails框架抛弃了这些配置文件,使用严格的约定,要求开发者将View.Controller.Model等各种类型文件放在自己专属的文件夹下,从而大大降低开发的复杂度,也即其Convention Over Configuration思想.       下图是一个典型的ROR应用程

Ruby On Rails学习笔记(4)——为first增加视图

         作为典型的MVC结构,绝对不会把显示的任务交给控制器,这需要有专业的视图来完成.在Rails中增加视图文件,同样是想当地的方便.下面就是为First应用程序的hello控制器增加index视图的详细步骤:        1.使用generate脚本生成视图:                   2.修改hello_controller.rb文件:                    3.在浏览器中查看自动生成的视图文件的显示效果:                       

Ruby On Rails学习笔记(3)——Rails程序由0到1

     正如Rails的理念一样,创建一个新的Rails应用程序的过程非常简单,下面就来看看如何从0到1建立一个全新的Rails应用程序.     1.启动InstantRails,打开其Rails应用程序管理器(Rails Application Manager):         2.创建一个名称为first的新的应用程序:              3.使用first应用程序中的脚本文件创建一个名称为hello的控制器:                   4.启动针对first应用程序

Python基础教程学习笔记 第一章 基础知识_Android

1.python的每一个语句的后面可以添加分号也可以不添加分号:在一行有多条语句的时候,必须使用分号加以区分 2.查看Python版本号,在Dos窗口中输入"python -V"查看版本号,注意V是大写字母,这条命令是Windows命令,而不是python shell的命令 3.让解释器只执行普通的除法运算:from __feture__ import division 4.执行整除运算的运算符:// 5.取幂运算符:2**4 相当于2的4次方,-2**4相当于2的4次方之后取负,因为

JavaScript高级程序设计(第3版)学习笔记2 js基础语法_基础知识

这一篇复习一下ECMAScript规范中的基础语法,英文好的朋友可以直接阅读官方文档.JavaScript本质上也是一种类C语言,熟悉C语言的朋友,可以非常轻松的阅读这篇文章,甚至都可以跳过,不过建议你最好还是看一看,在介绍的同时,我可能会引用一些自认为不易理解且比较流行的用法. 基础语法 1.标识符:所谓标识符,实际上就是指一个满足一定规范,能够被引擎识别的名字,可以用来表示常量.变量.函数名.函数参数.对象.对象属性等所有可命名对象的名称. (1)区分大小写. (2)以字母.下划线(_)或美