赵龙 全栈之路

Rails 实战——图书管理系统——基础建设

| Comments

目标

搭建 rails 项目的基础

注意两个 “+….” 符号中间的代码,是新增代码

1、确认操作环境

进入终端页面

ruby -v
#=> ruby 2.3.1p112

rails -v
#=> Rails 5.1.4

常用终端指令

git status  # 查看 git 状态
rake routes # 查看路由

2、建立 Rails 专案

rails new library01
cd library01
git init
git add .
git commit -m "First Commit"

2.1 安装 Mysql 数据库

git checkout -b ch01
# 建立新分支

修改 Gemfile 文件

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.1.4'
- # Use sqlite3 as the database for Active Record
- gem 'sqlite3'
+ # Use mysql2 as the database for Active Record
+ gem 'mysql2'

2.2 修改数据库配置文件

文件 config/database.yml 修改为下面形式

development:
  adapter: mysql2       #数据库类型
  database: rails01     #数据库名字(需要修改)
  username: root        #用户名
  password:             #用户密码
  host: localhost       #ip地址


production:
  adapter: mysql2
  database: rails01
  username: root
  password:
  host: localhost
# 启动 Mysql 数据库
mysql.server start

# 建立数据库
rake db:create

git status
git add .
git commit -m "install mysql"

3、建立 Welcome 页面

在文件 config/routes.rb 添加 welcome 页面路由

config/routes.rb
Rails.application.routes.draw do
  root 'welcome#index' # 确定首页路由
end

新建文件 touch app/controllers/welcome_controller.rb

app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
  def index
  end
end

新建文件夹 mkdir app/views/welcome
新建文件 touch app/views/welcome/index.html.erb

app/views/welcome/index.html.erb
<h1>Hello World</h1>

再开一个终端页面,执行 rails s
打开 http://localhost:3000 页面

git add .
git commit -m "implement welcome#html"

4、布置网站样式

4.1 将 Bootstrap 的 CSS 套件装进专案里面

Gemfile

+ gem 'bootstrap-sass'

group :development, :test do

修改文件名,终端输入

mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss

然后修改 app/assets/stylesheets/application.scss 档案,在最后加入以下两行

/*
 * ...(一堆注解)
 *= require_tree .
 *= require_self
 */

+ @import "bootstrap-sprockets";
+ @import "bootstrap";

将变更 commit 进 git 里面
git add .
git commit -m "add bootstrap to project"

4.2 修改 Views 样式

修改文件 app/views/layouts/application.html.erb

  <head>
-   <title>Rails05</title>
+   <title>图书管理系统</title>

  <body>
-   <%= yield %>
+......
    <div class="container-fluid">
      <%= render "common/navbar" %>
      <%= yield %>
    </div>
    <%#= render "common/footer" %>
+......   
  </body>

4.3新增 navbar

新增 app/views/common 资料夹
mkdir app/views/common

新增 navbar 导航栏
touch app/views/common/_navbar.html.erb

填入 app/views/common/_navbar.html.erb

<nav class="navbar navbar-default" role="navigation">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <a class="navbar-brand" href="/">图书管理系统</a>
            <!-- href="#"是点击按钮跳转路径,将符号"#"替换为相对网址路径,例如"/"表示首页路径 -->
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav navbar-right">
                <li><%= link_to("登录", '#') %></li>
                <!-- 在 rails 中 "link_to" 是 "<a>" 的封装 -->
            </ul>
        </div>
        <!-- /.navbar-collapse -->
    </div>
    <!-- /.container-fluid -->
</nav>

4.4新增 footer

touch app/views/common/_footer.html.erb

填入app/views/common/_footer.html.erb

<footer class="container-fluid navbar-fixed-bottom" style="margin-top: 100px;">
    <p class="text-center">图书管理系统
        <br>Planck1043
    </p>
</footer>
git add .
git commit -m "update view style"

参考资料:

5、安装 flash 消息提示功能

5.1 将 Boostrap 的 js 提示套件 bootstrap/alert “挂”进专案里面

requre_tree 上加入一行 //= require bootstrap/alert
app/assets/javascripts/application.js

... (一堆注解)
//= require jquery_ujs
//= require turbolinks
+//= require bootstrap/alert
//= require_tree .

5.2 新增 app/views/common/_flashes.html.erb

touch app/views/common/_flashes.html.erb

填入 app/views/common/_flashes.html.erb

<% if flash.any? %>
  <% user_facing_flashes.each do |key, value| %>
    <div class="alert alert-dismissable alert-<%= flash_class(key) %>">
      <button class="close" data-dismiss="alert">×</button>
      <%= value %>
    </div>
  <% end %>
<% end %>

5.3 加入 app/helpers/flashes_helper.rb

touch app/helpers/flashes_helper.rb

填入以下内容:
app/helpers/flashes_helper.rb

module FlashesHelper
  FLASH_CLASSES = { alert: "danger", notice: "success", warning: "warning"}.freeze

  def flash_class(key)
    FLASH_CLASSES.fetch key.to_sym, key
  end

  def user_facing_flashes
    flash.to_hash.slice "alert", "notice","warning" 
  end
end

5.4 在 application.html.erb 内加入 flash 这个 partial

<%= yield %> 前加入 <%= render "common/flashes" %>

app/views/layouts/application.html.erb

+ <%= render "common/flashes" %>
  <%= yield %>

5.5 git 存档

git add .
git commit -m "add bootstrap flash function"

5.6 测试 flash helper 的功能(可以略过)

加入 flash[:notice] = "早安!你好!"。你应该可以看到系统跳出“绿色”提示窗。

app/controllers/welcome_controller.rb

class WelcomeController < ApplicationController
  def index
    flash[:notice] = "早安!你好!"
  end
end

6、安装 Sorcery(轻量级会员系统)

devisesorcery 都是会员系统。

devise是重量级的,sorcery是轻量级的。

安装gem

Gemfile

+ gem 'sorcery'

group :development, :test do

终端执行 $ bundle install
重启 $ rails s

初始化安装

$ rails g sorcery:install

如何安装sorcery提供的子功能(可以忽略)

比如下面的重置密码功能,可以参考config/initializers/sorcery.rb文件
$ rails generate sorcery:install reset_password --only-submodules

配置参数文件

配置文件/config/initializers/sorcery.rb,这些地方需要配置,将激活功能删除,减少配置的复杂度

user.user_activation_mailer = nil
user.activation_mailer_disabled = true
user.prevent_non_active_users_to_login = false

Sorcery具体使用

sorcery只有针对密码的加密功能,但是没有针对密码的校验和密码一致性的校验。执行上面的模块建立方式:

$ rails g sorcery:install remember_me reset_password user_activation --only-submodules
config/initializers/sorcery.rb参考如上的配置方式。

修改文件 config/routes.rb

Rails.application.routes.draw do
  root 'welcome#index'
  resources :users
  resources :sessions
end

终端执行 rake db:migrate

配置文件 model/user.rb

class User < ApplicationRecord
  authenticates_with_sorcery!
  attr_accessor :password, :password_confirmation

  validates_presence_of :email, message: "邮箱不能为空"
  validates :email, uniqueness: true
  validates_presence_of :password, message: "密码不能为空",
    if: :need_validate_password
  validates_presence_of :password_confirmation, message: "密码确认不能为空",
    if: :need_validate_password
  validates_confirmation_of :password, message: "密码不一致",
    if: :need_validate_password
  validates_length_of :password, message: "密码最短6位",
    minimum: 6,
    if: :need_validate_password

  private
  
  def need_validate_password
    self.new_record? ||
      (!self.password.nil? or !self.password_confirmation.nil?)
  end
end

配置文件 app/controllers/users_controller.rb

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  #用户注册
  def create
    @user = User.new(params.require(:user)
      .permit(:email, :password, :password_confirmation))

    if @user.save
      flash[:notice] = '注册成功,请登录'
      redirect_to new_session_path
    else
      render action: :new
    end
  end

  #用户密码修改
  def change_password
    if current_user.valid_password?(params[:old_password])
      current_user.password_confirmation = params[:password_confirmation]

      if current_user.change_password!(params[:password])
        render json: {status: 'ok', msg: '密码修改成功'}
      else
        render json: {status: 'error', msg: current_user.errors.messages.values.flatten}
      end
    else
      render json: {status: 'error', msg: '旧密码不正确'}
    end
  end

  #用户发送忘记密码邮件,这里需要对邮件进行配置
  def send_forget_password_email
    @user = User.find_by(email: params[:email])
    if @user
      @user.deliver_reset_password_instructions!
      render json: {status: 'ok', msg: "重置密码的链接已发送到上面的邮箱"}
    else
      render json: {status: 'error', msg: '指定邮箱不存在'}
    end
  end

  #密码重置
  def reset_password
    @user = User.load_from_reset_password_token(params[:token])
    if @user
      @user.password_confirmation = params[:password_confirmation]
      if @user.change_password!(params[:password])
        render json: {status: 'ok', msg: '密码修改成功'}
      else
        render json: {status: 'error', msg: @user.errors.messages.values.flatten}
      end
    else
      render json: {status: 'error', msg: 'token不正确或者已过期'}
    end
  end
end

配置文件 app/views/users/new.html.erb

<h1>用户注册</h1>
<div>
  <% unless @user.errors.empty? %>
    <ul>
      <% @user.errors.messages.values.flatten.each do |error| %>
        <li><%= error %></li>
      <% end -%>
    </ul>
  <% end -%>
</div>
<%= form_for :user, url: users_path, method: :post, html: { class: 'form-horizontal', id: "user_form"} do |f| %>
  <div class="form-group">
    <div class="col-lg-12">邮箱 *</div>
    <div class="col-lg-12">
      <%= f.text_field :email, class: "form-control" %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">密码 *</div>
    <div class="col-lg-12">
      <%= f.password_field :password, class: "form-control" %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">密码确认 *</div>
    <div class="col-lg-12">
      <%= f.password_field :password_confirmation, class: "form-control" %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">
      <div class="text-center">
        <a href="<%= new_session_path %>">登录</a>
      </div>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">
      <input type="submit" name="create_user_submit" value="创建账户" class="col-xs-12 btn btn-primary">
    </div>
  </div>
<% end %>

配置文件 app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  before_action :auth_user, except: [:destroy]

  def new
  end

  def create
    #login是sorcery的登录方法
    if user = login(params[:email], params[:password])
      flash[:notice] = '登陆成功'
      redirect_to root_path
    else
      flash[:notice] = "邮箱或者密码错误"
      redirect_to new_session_path
    end
  end

  def destroy
    #logout是sorcery的退出方法
    logout
    flash[:notice] = "退出登陆"
    redirect_to root_path
  end

  private

  def auth_user
    #logged_in?是sorcery的判断登录方法
    if logged_in?
      redirect_to root_path
    end
  end
end

配置文件 app/views/sessions/new.html.erb

<h1>用户登录</h1>
<%= form_tag sessions_path, method: :post, class: "form-horizontal" do %>
  <div class="form-group">
    <div class="col-lg-12">邮箱</div>
    <div class="col-lg-12">
      <%= text_field_tag :email, nil, class: "form-control" %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">密码</div>
    <div class="col-lg-12">
      <%= password_field_tag :password, nil, class: "form-control" %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">
      <div class="text-center">
        <a href="<%= new_user_path %>">注册</a>
      </div>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">
      <input type="submit" name="sign_submit" value="登陆" class="col-xs-12 btn btn-primary">
    </div>
  </div>
<% end %>

参考资料:

Sorcery(轻量级会员系统)的使用

| Comments

devisesorcery 都是会员系统。

devise是重量级的,sorcery是轻量级的。

安装gem

Gemfile

+ gem 'sorcery'

group :development, :test do

终端执行 $ bundle install
重启 $ rails s

初始化安装

$ rails g sorcery:install

如何安装sorcery提供的子功能

比如下面的重置密码功能,可以参考config/initializers/sorcery.rb文件
$ rails generate sorcery:install reset_password --only-submodules

配置文件/config/initializers/sorcery.rb,这些地方需要配置,将激活功能删除,减少配置的复杂度

user.user_activation_mailer = nil
user.activation_mailer_disabled = true
user.prevent_non_active_users_to_login = false

2 Sorcery具体使用
sorcery只有针对密码的加密功能,但是没有针对密码的校验和密码一致性的校验。执行上面的模块建立方式:

$ rails g sorcery:install remember_me reset_password user_activation --only-submodules
config/initializers/sorcery.rb参考如上的配置方式。
配置文件 model/user.rb

class User < ApplicationRecord
  authenticates_with_sorcery!
  attr_accessor :password, :password_confirmation

  validates_presence_of :email, message: "邮箱不能为空"
  validates :email, uniqueness: true
  validates_presence_of :password, message: "密码不能为空",
    if: :need_validate_password
  validates_presence_of :password_confirmation, message: "密码确认不能为空",
    if: :need_validate_password
  validates_confirmation_of :password, message: "密码不一致",
    if: :need_validate_password
  validates_length_of :password, message: "密码最短6位",
    minimum: 6,
    if: :need_validate_password

  private
  
  def need_validate_password
    self.new_record? ||
      (!self.password.nil? or !self.password_confirmation.nil?)
  end
end

配置文件 app/controllers/users_controller.rb

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  #用户注册
  def create
    @user = User.new(params.require(:user)
      .permit(:email, :password, :password_confirmation))

    if @user.save
      flash[:notice] = '注册成功,请登录'
      redirect_to new_session_path
    else
      render action: :new
    end
  end

  #用户密码修改
  def change_password
    if current_user.valid_password?(params[:old_password])
      current_user.password_confirmation = params[:password_confirmation]

      if current_user.change_password!(params[:password])
        render json: {status: 'ok', msg: '密码修改成功'}
      else
        render json: {status: 'error', msg: current_user.errors.messages.values.flatten}
      end
    else
      render json: {status: 'error', msg: '旧密码不正确'}
    end
  end

  #用户发送忘记密码邮件,这里需要对邮件进行配置
  def send_forget_password_email
    @user = User.find_by(email: params[:email])
    if @user
      @user.deliver_reset_password_instructions!
      render json: {status: 'ok', msg: "重置密码的链接已发送到上面的邮箱"}
    else
      render json: {status: 'error', msg: '指定邮箱不存在'}
    end
  end

  #密码重置
  def reset_password
    @user = User.load_from_reset_password_token(params[:token])
    if @user
      @user.password_confirmation = params[:password_confirmation]
      if @user.change_password!(params[:password])
        render json: {status: 'ok', msg: '密码修改成功'}
      else
        render json: {status: 'error', msg: @user.errors.messages.values.flatten}
      end
    else
      render json: {status: 'error', msg: 'token不正确或者已过期'}
    end
  end
end

配置文件 app/views/users/new.html.erb

<h1>用户注册</h1>
<div>
  <% unless @user.errors.empty? %>
    <ul>
      <% @user.errors.messages.values.flatten.each do |error| %>
        <li><%= error %></li>
      <% end -%>
    </ul>
  <% end -%>
</div>
<%= form_for :user, url: users_path, method: :post, html: { class: 'form-horizontal', id: "user_form"} do |f| %>
  <div class="form-group">
    <div class="col-lg-12">邮箱 *</div>
    <div class="col-lg-12">
      <%= f.text_field :email, class: "form-control" %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">密码 *</div>
    <div class="col-lg-12">
      <%= f.password_field :password, class: "form-control" %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">密码确认 *</div>
    <div class="col-lg-12">
      <%= f.password_field :password_confirmation, class: "form-control" %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">
      <div class="text-center">
        <a href="<%= new_session_path %>">登录</a>
      </div>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">
      <input type="submit" name="create_user_submit" value="创建账户" class="col-xs-12 btn btn-primary">
    </div>
  </div>
<% end %>

配置文件 app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  before_action :auth_user, except: [:destroy]

  def new
  end

  def create
    #login是sorcery的登录方法
    if user = login(params[:email], params[:password])
      flash[:notice] = '登陆成功'
      redirect_to root_path
    else
      flash[:notice] = "邮箱或者密码错误"
      redirect_to new_session_path
    end
  end

  def destroy
    #logout是sorcery的退出方法
    logout
    flash[:notice] = "退出登陆"
    redirect_to root_path
  end

  private

  def auth_user
    #logged_in?是sorcery的判断登录方法
    if logged_in?
      redirect_to root_path
    end
  end
end

配置文件 app/views/sessions/new.html.erb

<h1>用户登录</h1>
<%= form_tag sessions_path, method: :post, class: "form-horizontal" do %>
  <div class="form-group">
    <div class="col-lg-12">邮箱</div>
    <div class="col-lg-12">
      <%= text_field_tag :email, nil, class: "form-control" %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">密码</div>
    <div class="col-lg-12">
      <%= password_field_tag :password, nil, class: "form-control" %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">
      <div class="text-center">
        <a href="<%= new_user_path %>">注册</a>
      </div>
    </div>
  </div>
  <div class="form-group">
    <div class="col-lg-12">
      <input type="submit" name="sign_submit" value="登陆" class="col-xs-12 btn btn-primary">
    </div>
  </div>
<% end %>

参考资料:

网站运行逻辑

| Comments

网站基本结构

*路由(Route): 前端(View) <=> 后台(Model与Controller) <=> 数据库(Mysql) *

Route:网站路由确定网址,当用户点击超链接按钮时,向网站后端发出对应的指令,调出相应的网页。
Model:网站调用与处理数据库数据的中心。
View:网页内容的前端展示台。
Controller:网站后台的控制中心。

网站运行基本逻辑

用户打开网站对应网址,通过路由(routes)向网站发送 get 指令,获取网站页面前端(views)页面,在网站上进行操作向网站后台(Model与Controller)发送 post 指令,对网站数据库执行对应操作,通过 get 指令更新前端(views)页面。
网站最重要的部分是数据库,前端(View) 与后台(Model与Controller)可以根据需要进行优化或更换相应的框架,都是为了更好的使用与操作数据库的数据。只有数据库不能轻易更换。

Routes

在互联网早期发展,网站的路由设置只有 GET(读取),POST(发送表单)两种方法:

  • GET(读取):读取网站页面信息(网络爬虫会自动执行GET)。
  • POST(新增):向网站发送表单,让网站数据库新增一条数据(本质是向网站发送表单,网站数据库根据表单内容执行操作)。

在网站运营过程中,发现这样的设置让代码越发庞大与难以维护,为了简化路由设置增加了其他的新方法,以 Ruby on Rails 为例:

  • PUT(更新):本质还是 POST 动作,让网站数据库执行某一条数据更新覆盖。
  • DELETE(删除):本质还是 POST 动作,让网站数据库执行数据删除。

参考资料:

Model

在 rails 中,Model 必须与数据库的数据表对应,rails 中的数据表不用僵硬的设置外键,在 Model 根据项目逻辑灵活设置关联关系即可。跟数据库相关数据的处理自定义为项目需要的方法,直接供相应的 Controller 调用。

参考资料:

Views

在 rails 中,"form_for" 表单是为了简化常用的 form 表单而存在,gem ‘simple_form’ 更进一步简化了。

参考资料:

Controllers

在 rails 中,Controller 是否顺利执行的关键在于准确接收前端(View)传递的参数,使用 gem 'pry' 可以查看前端传递的参数。
设定前端参数的方法

# app/controllers/books_controller.rb
  def createa
    @book = Book.new(                
    :title => params[:book_title],  #手动设定接受前端参数
    :text => params[:book_text]
    )
  
    if @book.save
      redirect_to books_path
    else
      render 'new'
    end
  end


# app/views/books/indexa.html.erb

<p>
  <% @books.each do |book| %>
    <tr class="text-info">
      <td><%= book.title %></td>
      <td><%= book.text %></td>
      <td><%= book.book_stock %></td>
      <td>
          <%= link_to '显示', showa_books_path(book) %><span style="margin-left: 5px;">|</span>
                                                      #正下方是:手动设定传递的前端参数
          <%= link_to '借阅', add_to_borrow_books_path(:id => book.id), :method => :post, :class => "btn btn-primary btn-lg btn-danger" %>
      </td>
    </tr>
  <% end %>

Rails Routes(路由) 中 GET、POST等方法的含义

| Comments

在互联网早期发展,网站的路由设置只有 GET(读取),POST(发送表单)两种方法:

  • GET(读取):读取网站页面信息(网络爬虫会自动执行GET)。
  • POST(新增):向网站发送表单,让网站数据库新增一条数据(实际上是向网站发送表单,网站数据库根据表单内容执行操作)。

在网站运营过程中,发现这样的设置让代码越发庞大与难以维护,为了简化路由设置增加了其他的新方法,以 Ruby on Rails 为例:

  • PUT(更新):本质还是 POST 动作,让网站数据库执行某一条数据更新覆盖。
  • DELETE(删除):本质还是 POST 动作,让网站数据库执行数据删除。

参考资料:

rails 前端传递参数查询

| Comments

项目介绍

Notice(通知)可以进行 CRUD 操作,在每条 Notice(通知)的 Show 页面可以发布 Post(评论),Post(评论)也可以进行 CRUD 操作。

1、鼠标悬浮 Delete 按钮上方

网址 http://localhost:3000/notices/2 ,表示这是 id:2 的 Notice(通知)。
页面右下角出现提示 http://localhost:3000/notices/13/posts/2 ,表示 id:3的Post(评论),关联 id:2 的 Notice(通知)。

2、路由解释

rails 项目的网址解析由文件 config/routes.rb 决定。详解 ———— Rails 路由全解

3、断点检测

使用 gem 'pry-rails' 实现断点检测。
在文件 app/controllers/posts_controller.rb 插入断点代码 binding.pry

执行命令 params ,可以查看程序暂停位置接受的参数。

蓝色标注,View(前端)传递的参数是 Hash{"notice_id"=>"12", "id"=>"2"}
,表示点击Post(评论)的 Delete 按钮,该Post(评论)的主键是 "notice_id"=>"12" ,关联 Notice(通知)的外键是"id"=>"2"。这与 View(前端)代码的具体写法直接相关,不同的写法传输的参数形式不一样。这决定了在 Controller (控制器)如何设定接受参数设定(正下方截图中的:notice_id)。

View(前端)

notice_post_path(post) 这是 rails 的内置路径代码写法,会自动生成固定写法的主键与外键字段的 key ,与 Model 与 db 文件的设定无关。

注意:Controller 接受参数的设定与 View(前端)的具体代码写法直接相关,可以通过 gem 'pry-rails' 确定。



执行 quit 或 next 退出 pry 调试状态,程序继续运行。

Rails Guides 通知发布系统 CRUD 教程(改进版)

| Comments

目标

建立一个可以发布,更新,删除的通知系统,通知由标题与正文构成。

1、确认操作环境

进入终端页面
ruby -v
rails -v

git status  # 查看 git 状态
rake routes # 查看路由

2、建立新 rails 专案

rails new rails001
cd rails001
git init
git add .
git commit -m "First Commit"

3、建立 Welcome 页面

git checkout -b ch01

在文件 config/routes.rb 添加 welcome 页面路由

config/routes.rb
Rails.application.routes.draw do
  root 'welcome#index' # 确定首页路由
end

新建文件 app/controllers/welcome_controller.rb

app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
  def index
  end
end

新建文件夹 app/views/welcome
新建文件 app/views/welcome/index.html.erb

app/views/welcome/index.html.erb
<h1>Hello World</h1>

再开一个终端页面,执行 rails s
打开 http://localhost:3000 页面

git add .
git commit -m "implement welcome#html"

通知页面

4、Routes

在文件 config/routes.rb 添加 notices 路由

config/routes.rb
* root 'welcome#index'
  resources :notices # 资源使用复数名词

查看专案路由
rake routes

4.1 Models

在建立数据库建立 Noitce 数据表(表名使用单数)
rails g migration notice

打开新生成文件 db/migrate/xxxx一堆数字xxxx_notice.rb

db/migrate/xxxx一堆数字xxxx_notice.rb
class Notice < ActiveRecord::Migration[5.0]
* def change
    create_table :notices do |t|
      t.string :title
      t.text   :text
 
      t.timestamps
    end
* end
end

rake db:create
rake db:migrate
重启 rails s

新建文件 app/models/notice.rb (Model)

app/models/notice.rb
class Notice < ApplicationRecord
end

进入 rails c
Notice
u = Notice.create(title: "Hello", text: "World")
Notice.all
exit

5、Create

新建文件 app/controllers/notices_controller.rb (表名使用单数)添加 def new

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
  def new
  end
end

新建文件夹 app/views/notices
新建文件 app/views/notices/new.html.erb

app/views/notices/new.html.erb
<h1>New Notice</h1>

打开 http://localhost:3000/notices/new 页面

现在,已经建立了 def new 方法对应的最基本静态页面,接下来完善动态动作与基本前端页面

修改文件 app/controllers/notices_controller.rb 修改 def new添加 def create

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
  def new
    @notice = Notice.new
  end

  def create
    @notice = Notice.new(notice_params) #使用 Notice 健壮参数”

    if @notice.save
      redirect_to notice_path @notice.id # 可以省略@notice.idrails会自动解析重定向
    else
      render 'new' # 简写代码render :partial => "new"
    end
  end
  
  private
  
  def notice_params  # 设定 Notice 健壮参数”
    params.require(:notice).permit(:title, :text)
  end
end

参考资料:
Render 與 Redirect_to 用法
Rails Guides 健壮参数

修改文件 app/views/notices/new.html.erb

app/views/notices/new.html.erb
<h1>New Notice</h1>
<%= form_for @notice do |f| %>
  <p>
    <%= f.label :title %> </br>
    <%= f.text_field :title %>
  </p>

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

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

刷新 http://localhost:3000/notices/new 页面


参考资料:
form_for使用总结

git add .
git commit -m "implement Notice#Create "

6、Read

修改文件 app/controllers/notices_controller.rb 添加 def show

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
* def create
  end
   
  def show
    @notice = Notice.find(params[:id]) #搜索 Notice  id
  end
end

新建文件 app/views/notices/show.html.erb

app/views/notices/show.html.erb
<h1>Show Notices</h1>
<p>
  <strong>Title:</strong>
  <%= @notice.title %>
</p>
<p>
  <strong>text:</strong>
  <%= @notice.text %>
</p>

打开 http://localhost:3000/notices/1 页面

git add .
git commit -m "implement implement Notice#Read"

7、添加数据验证

参考资料: Rails 入门 5.10添加验证
修改文件 app/models/notice.rb ,在 Model 层添加数据验证。

app/models/notice.rb
class Notice < ApplicationRecord
  validates :title, presence: true,      #标题不得为空
                  length: { minimum: 5 } # 标题最短5个字符
end

修改文件 app/views/notices/new.html.erb ,在 View 层实现 “验证失败” 的提示

app/models/notice.rb
#<h1>New Notice</h1>
#<%= form_for @notice do |f| %>
  <% if @notice.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@notice.errors.count, "error") %> prohibited
        this notice from being saved:
      </h2>
      <ul>
        <% @notice.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>
* <p>
*   <%= f.label :title %> </br>

git add .
git commit -m "add data validation"

8、Update

修改文件 app/controllers/notices_controller.rb 添加 def edit & def update

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
* def show
   
  def edit
    @notice = Notice.find(params[:id])
  end

  def update
    @notice = Notice.find(params[:id])

    if @notice.update(notice_params)
      redirect_to notice_path @notice.id # 可以省略@notice.idrails会自动解析
    else
      render 'edit'
    end
  end
end

新建文件 app/views/notices/edit.html.erb

app/views/notices/edit.html.erb
<h1>Edit Notice</h1>
<%= form_for @notice do |f| %>
  <% if @notice.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@notice.errors.count, "error") %> prohibited
        this notice from being saved:
      </h2>
      <ul>
        <% @notice.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_field :text %>
  </p>

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

打开 http://localhost:3000/notices/1/edit 页面

git add .
git commit -m "implement Notice#Update"

8.1、使用局部视图简化代码

参考资料:
Rails 入:5.12 使用局部视图去掉视图中的重复代码
Rails 布局和视图渲染

新建 app/views/notices/_form.html.erb

app/views/notices/_form.html.erb
<%= form_for @notice do |f| %>
  <% if @notice.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@notice.errors.count, "error") %> prohibited
        this notice from being saved:
      </h2>
      <ul>
        <% @notice.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_field :text %>
  </p>

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

修改 app/views/notices/new.html.erb 为 下面的形式

app/views/notices/new.html.erb
<h1>New Notice</h1>

<%= render 'form' %>  <!-- 加载form局部视图 -->

<%= link_to 'Back', notices_path %>

修改 app/views/notices/edit.html.erb 为 下面的形式

app/views/notices/edit.html.erb
<h1>Edit Notice</h1>

<%= render 'form' %>  <!-- 加载form局部视图 -->

<%= link_to 'Back', notices_path %>

git add .
git commit -m "add local page to new & edit html"

9、Index

修改文件 app/controllers/notices_controller.rb 添加 def index

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
  def index
    @notices = Notice.all
  end
  
* def show
end

新建文件 app/views/notices/index.html.erb

app/views/notices/index.html.erb
<h1>Listing Notices</h1>
</p>
<%= link_to 'New', new_notice_path %>  #发布新通知按钮
</p>

<table>
  <tr>
    <th>Title</th>
    <th>Text</th>
  </tr>

  <% @notices.each do |notice| %>
    <tr>
      <td><%= notice.title %></td>
      <td><%= notice.text %></td>
      <td><%= link_to 'Show', notice_path(notice) %></td>
      <td><%= link_to 'Edit', edit_notice_path(notice) %></td>      
    </tr>
  <% end %>
</table>

git add .
git commit -m "implement Notice#index

10、Delete

修改文件 app/controllers/notices_controller.rb 添加 def index

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
* def update

  def destroy
    @notice = Notice.find(params[:id])
    @notice.destroy

    redirect_to notices_path
  end
end

修改文件 app/views/notices/index.html.erb

app/views/notices/index.html.erb
*     <td><%= link_to 'Show', notice_path(notice) %></td>
*     <td><%= link_to 'Edit', edit_notice_path(notice) %></td>
      <td><%= link_to 'Delete', notice_path(notice),
              method: :delete,
              data: { confirm: 'Are you sure' } %></td>

git add .
git commit -m "implement Noitce#Delete"

11、添加链接

在 show 页面最下方加入 Edit 链接

<%= link_to 'Edit', edit_notice_path %>

在 new、show、edit 页面最下方加入 Back 链接

<%= link_to 'Back', notices_path %>

git add .
git commit -m "Add edit and back page links"

参考文章:

Rails Guides 通知发布系统 CRUD 教程(基础版)

| Comments

目标

建立一个可以发布,更新,删除的通知系统,通知由标题与正文构成。

确认操作环境

进入终端页面
ruby -v
rails -v

建立新 rails 专案

rails new rails001
cd rails001
git init
git add .
git commit -m "First Commit"

建立 Welcome 页面

git checkout -b ch01

在文件 config/routes.rb 添加 welcome 页面路由

config/routes.rb
Rails.application.routes.draw do
  root 'welcome#index'
end

新建文件 app/controllers/welcome_controller.rb

app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
  def index
  end
end

新建文件夹 app/views/welcome
新建文件 app/views/welcome/index.html.erb

app/views/welcome/index.html.erb
<h1>Hello World</h1>

再开一个终端页面,执行 rails s
打开 http://localhost:3000 页面

git add .
git commit -m "implement welcome#html"

通知页面

Routes

在文件 config/routes.rb 添加 notices 路由

config/routes.rb
  root 'welcome#index'
+ resources :notices

查看专案路由
rake routes

Models

在建立数据库建立 Noitce 数据表
rails g migration notice

打开新生成文件 db/migrate/xxxx一堆数字xxxx_notice.rb

db/migrate/xxxx一堆数字xxxx_notice.rb
class Notice < ActiveRecord::Migration[5.0]
  def change
+   create_table :notices do |t|
+     t.string :title
+     t.text   :text
+
+     t.timestamps
    end
  end
end

rake db:create
rake db:migrate

新建文件 app/models/notice.rb (Model)

app/models/notice.rb
class Notice < ApplicationRecord
end

进入 rails c
Notice
u = Notice.create(title: "Hello", text: "World")
Notice.all
exit

Create

新建文件 app/controllers/notices_controller.rb 添加 def new

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
  def new
  end
end

新建文件夹 app/views/notices
新建文件 app/views/notices/new.html.erb

app/views/notices/new.html.erb
<h1>New Notice</h1>

打开 http://localhost:3000/notices/new 页面

修改文件 app/controllers/notices_controller.rb 修改 def new添加 def create

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
  def new
    @notice = Notice.new
  end

  def create
    @notice = Notice.new(
      :title => params[:notice][:title],
      :text => params[:notice][:text]
      )

    if @notice.save
      redirect_to @notice
    else
      render 'new'
    end
  end
end

修改文件 app/views/notices/new.html.erb

app/views/notices/new.html.erb
<h1>New Notice</h1>
<% form_for @notice do |f| %>
  <p>
    <%= f.label :title %> </br>
    <%= f.text_field :title %>
  </p>

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

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

刷新 http://localhost:3000/notices/new 页面

Read

修改文件 app/controllers/notices_controller.rb 添加 def show

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
 # def create
   end
   
  def show
    @notice = Notice.find(params[:id])
  end
end

新建文件 app/views/notices/show.html.erb

app/views/notices/show.html.erb
<h1>Show Notices</h1>
<p>
  <strong>Title:</strong>
  <%= @notice.title %>
</p>
<p>
  <strong>text:</strong>
  <%= @notice.text %>
</p>

打开 http://localhost:3000/notices/1 页面

Update

修改文件 app/controllers/notices_controller.rb 添加 def edit & def update

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
# def show
   
  def edit
    @notice = Notice.find(params[:id])
  end

  def update
    @notice = Notice.find(params[:id])

    if @notice.update(
      :title => params[:notice][:title],
      :text => params[:notice][:text]
      )
      redirect_to notice_path
    else
      render 'edit'
    end
  end
end

新建文件 app/views/notices/edit.html.erb

app/views/notices/edit.html.erb
<h1>Edit Notice</h1>
<%= form_for @notice do |f| %>
  <p>
    <%= f.label :title %> </br>
    <%= f.text_field :title %>
  </p>

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

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

打开 http://localhost:3000/notices/1/edit 页面

Index

修改文件 app/controllers/notices_controller.rb 添加 def index

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
  def index
    @notices = Notice.all
  end
  
# def show
end

新建文件 app/views/notices/index.html.erb

app/views/notices/index.html.erb
<h1>Listing Notices</h1>
</p>
<%= link_to 'New', new_notice_path %>
</p>

<table>
  <tr>
    <th>Title</th>
    <th>Text</th>
  </tr>

  <% @notices.each do |notice| %>
    <tr>
      <td><%= notice.title %></td>
      <td><%= notice.text %></td>
      <td><%= link_to 'Show', notice_path(notice) %></td>
      <td><%= link_to 'Edit', edit_notice_path(notice) %></td>      
    </tr>
  <% end %>
</table>

Delete

修改文件 app/controllers/notices_controller.rb 添加 def index

app/controllers/notices_controller.rb
class NoticesController < ApplicationController
# def update

  def destroy
    @notice = Notice.find(params[:id])
    @notice.destroy

    redirect_to notices_path
  end
end

修改文件 app/views/notices/index.html.erb

app/views/notices/index.html.erb
#     <td><%= link_to 'Show', notice_path(notice) %></td>
#     <td><%= link_to 'Edit', edit_notice_path(notice) %></td>
      <td><%= link_to 'Delete', notice_path(notice),
              method: :delete,
              data: { confirm: 'Are you sure' } %></td>

git add .
git commit -m "implement Noitce CRUD"

添加链接

在 show 页面最下方加入 Edit 链接
<%= link_to 'Edit', edit_notice_path %>

在 new、show、edit 页面最下方加入 Back 链接
<%= link_to 'Back', notices_path %>

参考文章:

Rails Guides 健壮参数

| Comments

传统的参数传送方式

app/controllers/notices_controller.rb
def create
    @notice = Notice.new(
      :title => params[:notice][:title], 
      :text => params[:notice][:text]
      )
    @notice.save

    redirect_to notices_path
  end 

代码 :text => params[:notice][:text] 中,:textsymbol 符号(简单解释:不可更改字符串)代表数据库中对应的 text 字段;params[:notice][:text] 表示从 View 层发送过来的参数(params), 第一个[]中的[:notice]代表数据库中表名为 notice 的数据表,第二个[]中的[:notice]代表该表的text字段。=> 符号表示符号左边的数据库字段接受右边从 View 层发送过来的参数。

健壮参数

  def create
    @article = Article.new(article_params) #使用健壮参数
    @article.save
    
    redirect_to @article
  end

  private
  
  # 设定健壮参数
  def article_params
    params.require(:article).permit(:title, :text)
  end

健壮参数中 params.require(:article).permit(:title, :text)require(:article) 对应数据库中数据表的名称 permit(:title, :text)对应该数据表的title 与 text两个字段
健壮参数不仅大大的简化了代码,同时也提高了网站的安全性

Rails Guides 实作 CRUD 顺序逻辑

| Comments

在 Ruby on Rails 中实现 CRUD 功能需要使用 RMVC ,实作顺序是 Route > Modle > Controller > View。

  • Routes :第一步实作路由(Route)处理网址,才能决定接下来 Model、Controller、View 的命名。
  • Modles :第二步实作模型(Model),才能处理与数据库相关的数据。
    • 注意:如果用户操作不涉及数据库,模型(Model)可省略。
  • Controllers :第三步实作控制器(Controller)中的各个方法(def),实现前端(View)展示的各个按钮功能。
  • Views :第四步实作整个前端页面(View),在后端(Model 与 Controller)提供的功能基础上优化前端页面。

debug 神器 gem 'pry-rails'

| Comments

使用说明

安装 gem

Gemfile
gem 'pry'
gem 'pry-rails'

终端执行 bundle install,记得 rails s 重启本地项目

插入断点测试代码 binding.pry

  def edit
    @notice = Notice.find(params[:id])
    binding.pry #程序运行到这里暂停
  end

点击 “Edit” 按钮测试

在终端本地运行项目的 rails s 页面,自动进入了 pry 调试状态。
打开变量 @notice ,可以看到变量 @notice 内部数据。

执行命令 params ,可以查看程序暂停位置接受的参数:


接受前端参数:





执行 quit 或 next 退出 pry 调试状态,程序继续运行。

Debug 神器 pry-rails 理解

在专案中插入的代码 binding.pry ,使程序运行到该位置时暂停,可以进行对程序运行中各个对象进行数据查看,通过对运行中的对象数据判断出 bug 的位置。传统 debug 只是根据报错提示进行操作相当于黑箱操作,难度系数很大。通过 pry-rails 将传统 debug 中的黑箱打开或部分打开,大大的降低了 debug 难度。

参考文章:

Rails Guides 零散笔记

| Comments

两种分支判断式:if & when

上下两段分支判断式代码等价,实现效果相同。

 1 a = 2 
 2 case a 
 3   when 1 then puts "a is 1" 
 4   when 2 then puts "a is 2" 
 5   when 3,4,5 then puts "a is in [3,4,5]" 
 6   else puts "a is not in [1,2,3,4,5]" 
 7 end 
 8  
 9 ##### 
10 a = 2 
11 if a == 1 
12   puts "a is 1" 
13 elsif a == 2 
14   puts "a is 2" 
15 elsif a == 3 
16   puts "a is in [3,4,5]" 
17 elsif a == 4 
18   puts "a is in [3,4,5]" 
19 elsif a == 5 
20   puts "a is in [3,4,5]" 
21 else 
22   puts "a is not in [1,2,3,4,5]" 
23 end

三元表达式

“三元表达式” 与 “普通实现方式” 实现效果相同,代码更简洁。

a = 2

# 三元表达式
puts a == 1 ? 'one' : 'not one'
> #=>  not one
 
# 普通实现方式 
if a == 1
  puts 'one'
else
  puts 'not one'
end
> #=>  not one

Rails Guides 感悟随笔

| Comments

在终端操作过程中,同一线程内的指令操作,按照时间的先后顺序执行,在一定条件下,后来的指令会覆盖先前的指令。

u = User.first
k = User.last

u = k

> k #=> User.last
> u #=> User.last

字母 “q” 与 “w” 都可以理解为 “标签” ,真正进行运算的是数据库里相对应的数据。同一时刻,一份数据可以拥有多个标签(可更改),一个标签只能对应一个数据或数据集(可更改)。

w = User.create(email: "333@qq.com", password: "111111")
q = w

#等价于上面的代码
q =w =User.create(email: "333@qq.com", password: "111111")

###
q.update(email: "323@qq.com")  

> q #=> ...(email: "323@qq.com")  
> w #=> ...(email: "323@qq.com") 

数据库中的数据对象(单条数据或数据表)可以同时拥有多个标签,每一个标签保存着创建时的数据快照(以最近一次更新数据为准),标签之间互相独立,没有影响。以下示例:针对标签 “p” 更新数据,标签 “k” 不会受到影响。
注意 updated_at(更新时间) 字段的不同。

p = User.last
k = User.last

> p #=> #<..., email: "777@qq.com", ..., updated_at: "2017-12-12 03:04:11">
> k #=> #<..., email: "777@qq.com", ..., updated_at: "2017-12-12 03:04:11">

k.update(email: "787@qq.com")

> p #=> #<..., email: "787@qq.com", ..., updated_at: "2017-12-12 03:11:40">
> k #=> #<..., email: "777@qq.com", ..., updated_at: "2017-12-12 03:04:11">

Routes

Rails.application.routes.draw do
  root 'welcome#index'
  resources :notices
end

在 routes 路由中 resources :复数名词

Controller

在 rails 中,在 Model(模型) 互相关联的两个数据表,在 Controller 中可以使用符号 . 进行关联简写代码,例如在正下方截图 @post.notice = @notice 中的 @post.notice 表示数据表 Post 关联的 Notice 的外键是。。。。



Rails Guides 中的 CRUD

| Comments

CRUD:读写数据

示例

u = User.first

= 左边的代码是被赋值的对象(按需求更改),右边的代码才是真正执行的代码(不可出错)。

在 ruby 中,简单指令可以省略 () ,例如,User.find 1 等价 User.find(1)

在编程中,散列表 也被称谓 哈希表

在终端操作中,ruby 中不同语句可以通过符号 . 连接起来,例如: User.new ,User.find(1).destroy

Create.创建

user = User.create(name: "David", occupation: "Code Artist")

代码 User.create 表示从 User 模型调取,第一个字母必须大写,代码 name: "David", 表示 属性名: "保存记录", 一次性保存多条记录使用 , 隔开。

user = User.new
user.name = "David"
user.occupation = "Code Artist"
user.save

User.create 直接储存到数据库,User.new 必须执行 user.save 指令后,才储存到数据库(user可设定)。

Read.读取

# 返回所有用户组成的集合
users = User.all

# 返回第一个用户
user = User.first #还可以使用 second、last等。

# 返回 id = 3 的用户
user = User.find 3

# 返回第一个名为 David 的用户
david = User.find_by(name: 'David')

# 查找所有名为 David,职业为 Code Artists 的用户,而且按照 created_at 反向排列
users = User.where(name: 'David', occupation: 'Code Artist').order(created_at: :desc)

find id 方法适合已知 id 快速查询 ,find_by(...) 适合数据库字段查询。

Update.更新

通过查询语句检索到 Active Record 对象后,使用赋值符号 = 修改其属性,再使用 save 再将其存入数据库。

user = User.find_by(name: 'David')
user.name = 'Dave'
user.save

使用散列的简写方式,指定属性名和属性值,可以直接保存到数据库,适合一次更新多个属性。例如:

user = User.find_by(name: 'David')
user.update(name: 'Dave', occupation: 'Code Artist')

如果想批量更新多个记录,可以使用类方法 update_all ,

User.update_all "max_login_attempts = 3, must_change_password = 'true'"

Delete.删除

检索到 Active Record 对象后还可以将其销毁,从数据库中删除。

# 删除用户名为 David 的用户
user = User.find_by(name: 'David')
user.destroy

# 删除整个 User 数据表
User.destroy_all

慎用 destroy_all 指令,将在数据库中删除全部 User 数据。

JD-store 相关的技术文章

| Comments

Routes

Modles

Views

Controllers

rails 101

RAILS 101 第二讲 GROUP CRUD

实用工具

Ruby on Rails 常用编程语法

| Comments

root 方法

root 方法指明如何处理根路径(/)上的请求。
root 路由应该放在路由文件的顶部,因为最常用的路由应该首先匹配。
root 路由只处理 GET 请求。

config/routes.rb
Rails.application.routes.draw do
  root to: 'pages#main'
  root 'pages#main' # 上一行代码的简易写法

# 我们还可以在命名空间和作用域中使用 root 方法,例如:
  namespace :admin do
    root to: "admin#index"
  end
 
  root to: "home#index"
end

Rails101 & JD—Store 常见英文单词

| Comments

常用重要代码

bundle install        捆绑安装
module                模块
method                方法
confirmation          确认

终端指令

uploader              上传
image                 图片
implement             实现
button                按钮
function              功能
checkout              查看
account               账户
payment               付款
mailer                信封

Gemfile

development           发展
test                  测试

基础建设

import                输入
app                   应用程序
views                 视图
common                共同的
layouts               布局
application           应用;运用
alert                 警报;提醒
flash                 闪现
freeze                冻结
slice                 片;一片
uploads               上传
public                公共的

Routes (网页操作链接.路由)

routes                路由;路线
config                配置
devise_for            设计(会员系统gem 相关)
member                会员
namespace             命名空间
resources             资源
config                配置
root                  根
draw                  绘制;绘画

alipay                支付宝
wechat                微信

Model (数据库)

model                 模型
string                字符串
integer               整数
text                  文本
migrate               迁移(v)
migration             数据库迁移
validates             只会验证
presence              存在

columns               列
default               默认
boolean               布尔(数学中表示“真或假”两种状态)
ture                  真
false                 假

mount                 安装;装载
source                资源
through               通过
cart_items            购物车_项目
name                  姓名
address               地址
order                 订购
pay                   付款
generate              生成;产生
token                 代币;符记
mail                  邮件
subject               主题

password              密码
confirmation          确认
seed                  种子
reset                 重启

title                 标题
list                  目录;明细
quantity              数量
price                 价格
description           描述

Views (前端)

self                  自我;自己
bootstrap             引导(引导程序)
sprockets             链轮
navbar                导航栏
footer                页脚
header                标头(网页顶端的标头)
collapse              折叠
example               例子

track                 跟踪
links                 链接
style                 样式
stylesheets           样式表
media                 媒体
decoration            装饰
underline             强调
confirm               确认;证实
trash                 垃圾

select                选择
count                 计数
total                 总计;总数;合计
clearfix              清除修复
colspan               合并单元格

role                  角色
navigation            导航
container             容器
fluid                 流体
primary               主要的
pull                  拉
padding               填充
bottom                底部
border                边
bordered              镶上
margin                页边
text                  文本 
row                   行
nav                   导航
pills                 丸
stacked               堆叠
max-width             最大-宽度

center                中心
registration          注册
danger                危险

dropdown              落下
menu                  菜单
dropdown-menu         下拉菜单
login                 登录
logout                注销
signup                注册
toggle                切换
generate              生成
caret                 没有
font                  字体

input                 输入
submit                提交(修改)
disable_with          禁止(重复提交表单等操作)
link_to               链接到(访问...网页)
present               当下的,现在的
thumb.url             拇指.网址
tag                   标签

Controller (网页控制中心)

controller            调节器
authenticate          认证
authenticate_user!    认证用户
admin                 管理
require               要求
admin_required        管理(权限)_要求
alert                 警报;提醒
notice                注意
warning               警告

product               产品
params                参数数组
permit                许可
path                  路径
redirect              重定向
render                表达;引入
data                  数据

notify                通知
deliver               交付

CRUD

Ruby on Rails 中 MVC 常见英文单词

| Comments

Git

commit 承诺

Modle

nil        零
null       空
destroy    破坏

unique     独特的
attribute  属性
Methods    方法
dependent  依赖的
private    私人的
ensure     确保
Active Record 活动记录
validation 验证
rollback   回滚
after_initialize ;  initialize(初始化)
after_find 回调
after_touch  ;  after(之后)  touch(触发),触发后
object     物体

decrement  减量
decrement_counter 递减计数器
delete       删除
delete_all   删除所有
increment  增量
increment_counter 增量计数器
toggle     切换
touch      触摸
update_column     更新列
update_columns    更新列(复数)
update_all        全部更新
update_counters   更新计数器
valid      有效的
setup      建立

references     引用
conditions     条件
through        通过
polymorphic    多态
class_name     班级名称
primary_key    主键
foreign_key    外键
invers_of      对面的(根据代码上下文语义猜测)
association    协会
association=(associate)  协会=(关联)
reload         重装

autosave       自动保存
counter_cache  计数器缓存
validate       验证
optional       可选的
readonly       只读
select         选择
includes       包括
source         资源
collection     采集
singular       单数
clear          清除
empty          空
size           尺寸
build          建立
exists         存在

extending      扩展
limit          限制
offset         偏移量
order          排序
distinct       不同,不一样的

proxy_association.owner          代理_关联.所有者
proxy_association.reflection     代理_关联.反射
proxy_association.target         代理_关联.目标
type           类型
parent         父母

find           找
create_with    创造
eager_load     急切_加载
from           从
group          组
having         有
joins          加入
left_outer_joins   左边_外_加入
lock           锁
none           没有
preload        预紧
references     引用
reorder        重新排序
reverse_order  相反的顺序
where          哪里
batch_size     批量_尺寸
start          开始
finish         结束
error_on_ignore    错误忽略
export         输出

Views

builder        建设者
shared         共享;共享的
partial        部分
locals         本地
render         表达;引入
renderer       渲染器
spacer_template   间隔_模板
template       模板

layouts        布局
redirect_to    重定向
redirect_back  重定向返回(上个页面)
head           头部
inline         内联
content_type   内容_类型
content_for    内容
location       位置;定位
status         状态
format         格式
except         去除
special        特别的;重要的
bad_request    错误的请求

auto_discovery_link_tag      自动_发现_链接_标签
javascript_include_tag       JavaScript_包括_标签
stylesheet_link_tag          样式表_链接_标签
image_tag                    图像_标签
video_tag                    视频_标签
audio_tag                    音频_标签

local_assigns      本地分配
shallow            浅的
concern            有关
member             成员;会员
preview            预览
static segment     静态片段
constraints        限制约束
root               根;根源
scope              范围

prepend            前置
append             附加
capture            捕获
distance           距离
second             秒
fields             领域
radio              无线电
buttons            按钮
options            选项

Controller

protected          保护
raise              提高
rescue             拯救
require            要求
request            请求
query              询问
permit             允许
accepts            接受
nested             嵌套
attributes for     属性
accepts_nested_attributes_for    接受_嵌套_属性
reset              重启
encrypted          加密
respond            响应(动词)
response           响应(名词)
skip               跳跃
ensure             确保
send               发送
data               数据
stream             流
attachment         附件
inline             一致
close              关闭
open               打开
force              强制
devise             设计

ruby 语法基本结构

| Comments

在 ruby 中,一切皆对象。

对象本质上就是状态加行为,状态保存于实例变量中,相同类的不同对象可以拥有不同的状态。

代码影响范围:类 > 模块 > 方法 > 块

类:表示对象的种类,所有对象都属于一种类。

类的程序语法
class 类名 # 类名的首字母必须大写
  类的定义
end
  • 实例:类的对象。
  • 继承:通过扩展已经定义的类创建新类的过程。
  • 父类:被继承的类。
  • 子类:创建的新类。 -
“类的继承”的程序语法
class 类名 < 父类名
  类的定义
end
“单例方法”程序语法实例
class << HeloWorld
  def hello(name)
   puts "#{name} said hello."
  end
end 

HelloWorld.hello("John")    #=> John said hello.

模块:与类表现形式相似,只表示事物的行为本身。

模块的程序语法
  module 模块名 # 模块名的首字母必须大写
    模块定义
  end
  • 模块不能拥有实例(对象)。
  • 模块不能被继承。
    • 定义类时使用 include,模块中的方法、常量就能被类使用。
  • 模块函数:使用 “模块名.方法名” 的形式调用模块中定义的方法。
    • 如果没有定义与模块的方法、常量等同名的名称,那么引用时就可以省略模块名。

方法:在 Ruby 中,所有有关对象的操作都被封装为方法。

方法的程序语法
  def 方法名(参数1,参数2,···)
    希望执行的处理
  end
  • 实例方法:接受者为一个对象(实例)的方法。
  • 类方法:接受者是类本身(类对象)的方法。
  • 函数式方法:没有接受者的方法。
  • 方法的标记法:“类名.方法名”、“类名::方法名”(与实际程序语法一致);“类名#方法名”(帮助文档或使用说明使用)。

块:调用方式时能与参数一起传递的多个处理集合。

“带块的方法调用”的程序语法
  对象.方法名(参数列表) do |块变量|
    希望循环的处理
  end
  
  或
  
  对象.方法名(参数列表) { |块变量|
    希望循环的处理
  }

网页结构 RMVC 解读

| Comments

全栈构建网站需要了解一个基本的概念—— RMVC

R——route,网站路由,当用户点击超链接按钮时,向网站后端发出对应的指令,调出相应的网页。
M——model,网站处理与调用后台数据库信息的中心。
V——view,网页内容的前端展示台。
C——controller,网站后端的控制中心。

点击网页链接,网站运作逻辑流程:R >> C >> M >> V

举个例子来解释,当你浏览任意网站时,点击一个超链接按钮,Route 会发送相应的指令到网站的控制中心 Controller ,Controller 指挥 Model 处理涉及到网站数据库的部分并发送给 View,View 再展现用户需要的网页前端内容。