動態

詳情 返回 返回

前端學Ruby:全棧論壇(地宮)項目一 - 動態 詳情

本來想做 buddha(菩薩)論壇的,發現自己參考的項目太難實現,猝

筆者回爐重修了一番,正好發現了 realworld,遂決定將 realworld 項目代替原先的 buddha 項目,還是要量力而行,不要一意孤行(項目規劃太大,浪費太多時間學習)

先介紹一下 realworld 項目

源碼:https://github.com/gothinkster/realworld

demo:https://demo.realworld.io/#/

UI:https://github.com/gothinkster/conduit-bootstrap-template

頁面分析:https://www.jianshu.com/p/6014a9fefabd

從頁面角度講,只有七個頁面,即

  • 首頁(index)
  • 文章詳情頁(article)
  • 登錄頁(login)
  • 註冊頁(register)
  • 寫文章頁(editor)
  • 設置頁(settings)
  • 個人頁(profile)

接口方面和數據結構直接看 文檔 就好,不説虛的,這個項目有19個接口,19個接口放其他語言要做多久?不知道,但 Ruby 應該花不了多少時間

介於此項目是個全棧項目,遂會前後端穿插地寫,項目名我起好了:地宮(Underground Palace)

文章目錄

搭建項目並部署

使用腳手架創建 article

穿上 bootstrap

新增fontawesome

device 用户體系

devise-i18n國際化

設置頁

個人頁

模型建立

查詢功能

訂閲功能

分頁功能

再次部署

logo設計

後記

搭建項目並部署

我們先新建項目

rails new underground-palace
cd list

然後去 config/routes.rb 中修改根目錄:

Rails.application.routes.draw do
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  # root "articles#index"
  root "rails/welcome#index"
end

我們通過 fly.io 來部署我們的服務,對其不過多介紹,具體可看上篇文章——前端學Ruby:唐詩項目部署優化

fly launch # 創建
fly deploy # 部署
fly open # 打開剛剛部署的項目

fly launch

此時訪問 https://underground-palace.fly.dev/ (這裏我們的 underground 少寫了一個字母,無傷大雅,後續已修正)就能看到剛還在本地新建的項目,是不是很快,有點意想不到的感覺

使用腳手架創建 article

rails 的一個特點是一個命令就做很多事情,例如接下來我們要用 rails generate scaffold 完成 article 的增刪改查

rails g scaffold article title:string description:string body:text 
rails db:migrate # 數據遷入

並且修改config/routes.rb

Rails.application.routes.draw do
  resources :articles
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  root "articles#index"
  # root "rails/welcome#index"
end

如此,用腳手架搭建的文章的增刪改查就完成了,是不是很快

增刪改查

穿上 bootstrap

realworld 項目是基於 bootstrap 的,我們需要下載 bootstrap 的 gem

這裏需要做一下説明,像 bootstrap-sass gem 是基於 bootstrap 3 的樣式,bootstrap gem 是最新版的 boostrap,也可以理解為 bootstrap 3 及一下可使用 bootstrap-sass,反之則用 boostrap

因為 realworld 是基於 bootstrap4.0.0,所以下載時我們需要先設定好版本。按照 readme 的步驟,在 gemfile 文件中引入 boostrapjquery-rails 包,再新增 common/footercommon/header 頁面,將模板代碼放進去

但是 readlworld 所提供的 bootstrap 和 線上版本 有差異,並不是直接引用能用(後續看到文檔中有現成的 模板,但不知道有沒有坑)

既然選擇了做用 bootstrap 來做UI,索性用最新的 bootstrap5

我們不按照 gem 方式引入 bootstrap,用 cssbundling-rails jsbundling-rails 來構建資源

bundle add cssbundling-rails jsbundling-rails 

查找我們與 css 相關的構建命令

rails | grep css

查看css

同理查看我們與 javascript 構建相關的命令

rails | grep javascript

我們下載 bootstrap,基於 yarn

rails css:install:bootstrap

下載 esbuild,也是基於yarn下載,

rails javascript:install:esbuild

但是報錯 Could not resolve "app/javascript/*.*"

window中下載esbuild報錯

不用慌,去package.json 修改 build 中的配置,將esbuild app/javascript/*.* --bundle --sourcemap... 改成 esbuild app/javascript/application.js --bundle --sourcemap...

並執行 npm run build 執行代碼,當然,有些文件需要隱藏的這裏不做過多描述

當能 build 成功後,我們開發就是用bin/dev 命令來開發

但因為筆者使用的是 window 系統,所以會因此報錯:

unset為linux命令,報錯

unset 不是 window 的命令,所以我們要改造,前往根目錄下的 Procfile.dev 修改:

web: set "PORT=" && rails s
css: yarn build:css --watch
js: yarn build --watch

此時執行 /bin/dev 就能啓動我們的項目了,其以上代碼是啓動 rails 服務,css 和 js 都是通過 yarn build 打包後監聽(watch)變化,所以能做到熱更新

新增fontawesome

按照好 bootstrap 後還不夠,還需要安裝圖標,例如我們常用的fontawesome

首先安裝 Font Awesome:

yarn add @fortawesome/fontawesome-free

然後在 config/initializers/assets.rb 添加以下內容:

Rails.application.config.assets.paths << Rails.root.join('node_modules/@fortawesome/fontawesome-free/webfonts')

最後在 app/assets/stylesheets/application.sass.scss 添加以下內容:

$fa-font-path: ".";

@import "@fortawesome/fontawesome-free/scss/fontawesome.scss";
@import "@fortawesome/fontawesome-free/scss/solid.scss";

接着就是把具體的 articlesarticles#showarticles#new頁面的模板樣式補充好

用户體系

我們使用 devise 來做我們的登錄註冊

安裝 devise gem 包

bundle add devise

運行以下命令生成 Devise 文件

rails g devise:install

創建一個用户模型(例如User),並運行以下命令生成 Devise 所需要的視圖和控制器:

rails g devise user

運行數據庫遷移以創建 Devise 所需要的表

rails db:migrate

如此這般,登錄註冊忘記密碼等一系列 CRUD 就做好了,我們只需要在 header.html.erb 中修改配置,將未登錄時顯示登錄註冊樣式即可,即

...
<% if !current_user %>
        <!-- 未登錄 -->
        <div class="col-md-3 text-end">
          <%= link_to '註冊', new_user_registration_path, class: 'btn btn-outline-primary me-2' %>
          <%= link_to '登入', new_user_session_path, class: 'btn btn-primary' %>
        </div>
<% else %>
 <!-- 登錄 -->
<% end %>
...

默認情況下,我們是看不到 devise 的視圖和控制器的,因為我們要修改 UI,所以將視圖釋放出來:

rails g devise:views

前往視圖層,修改views/devise/registrations/new.html.erb (註冊頁)和views/devise/session/new.html.erb(登錄頁)的樣式

默認情況下,註冊、登錄的路由是users/sign_upusers/sign_in,和傳統意義上的註冊、登錄路由不符,這裏做一下映射,前往config/routes.rb中修改:

Rails.application.routes.draw do
    
  - devise_scope :user
  + devise_scope :user do
  +   get '/login' => 'devise/sessions#new'
  +   get '/register' => 'devise/registrations#new'
  + end
    ...
end

並前往views/common/_header.html.erb 中修改代碼:

<!-- 未登錄 -->
<div class="col-md-3 text-end">
  <%= link_to '註冊', register_path, class: 'btn btn-outline-primary me-2' %>
  <%= link_to '登入', login_path, class: 'btn btn-primary' %>
</div>

靜態頁面放進後,現在我們要考慮的是將其動態化,首先改造的是註冊頁面,我們用form_for 來做表單,這裏需要注意的是,在 devise 默認的字段裏沒有 username,我們需要加上

創建一個 migration 文件,用於向 User 模型添加 username 字段

rails g migration AddUsernameToUser username:string:uniq
uniq表示唯一

將這個 migration 遷移至數據庫

rails db:migrate

models/user.rb 中新增對 username 的驗證

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  validates :username, presence: true, uniqueness: { case_sensitive: false }, length: { minimum: 3, maximum: 25 }

end
  • presence: true 驗證:該屬性必須存在(不能為 nil 或空白字符串)
  • uniqueness: { case_sensitive: false } 驗證:該屬性的值必須是唯一的(即數據庫中不存在相同的值)。此外,該驗證規則將忽略大小寫,因此類似的兩個字符串,例如 abcABC,將被認為是相等的
  • length: { minimum: 3, maximum: 25 } 驗證:該屬性的長度必須介於 3 到 25 個字符之間

修改註冊頁面視圖,新增用户名樣式

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  ...
  <div class="form-group mb-3">
    <%= f.text_field :username, autofocus: true, autocomplete: "username", 
    class: "form-control form-control-lg",
    placeholder: "用户名" %>
  </div>
  ...
<% end %>

在改造時,我們還需要生成 devise 的控制器,讓表單在提交時前往正確的控制器處(因為我們定製了登錄註冊路徑,而不是用默認的,所以還要改造)

rails g devise:constroller -c # 生成所有 devise 的控制器

再在 config/routes.rb 中修改

 ...
 devise_for :users, path: "", path_names: {
    sign_in: "login",
    sign_out: "logout",
    sign_up: "register" 
  }, controllers: {
    registrations: "users/registrations",
    sessions: "users/sessions",
  }
  devise_scope :user do
    get '/login' => 'devise/sessions#new'
    get '/register' => 'devise/registrations#new'
  end
  ...

如此,註冊頁面就改造完了,繼續改造登錄頁面

devise-i18n國際化

當我們做完登錄頁之後,提示報錯信息還都是英文的,這次需要引入 i18n 來做中文提示

老規矩,先安裝 devise-i18n gem

bundle add devise-i18n

config/application.rb 文件中添加如下代碼:

config.i18n.default_locale = "zh-CN"

執行 devise:i18n 生成中文命令

rails generate devise:i18n:locale zh-CN

再去config/locales/devise.zh-CN.yml 中修改不滿意的翻譯,如此就完成了國際化

如此我們已經完成了5個頁面,即首頁、文章詳情頁、登錄頁、註冊頁、寫文章頁,還剩下設置頁和個人頁

設置頁

如果説 article 和 user 是通過命令行來生成的,那麼接下來的兩個頁面(設置、個人頁),就是我們正常開發時的開發流程

先創建一個 Settings 控制器:

rails g controller Settings index

config/routes.rb 中新增一個 "seetings" (單數資源)資源路由,開放 show 和 update :

resource :settings, only: [:show, :update]

創建 app/views/settings/index.html.erb 頁面,加上 bootstrap 樣式,settings 的靜態頁面就能訪問了

看靜態頁面我們就知道,users 數據中我們還缺少頭像(avatar)和簡介(bio),所以我們需要在 users 表中新增兩個字段

生成一個遷移文件,該文件添加 avatar 和 bio 列到 users 表中

rails g migration AddAvatarAndBioToUsers avatar:string bio:string

運行 rails db:migrate 修改數據庫中的表

rails db:migrate

接着我們前往 settings_controller.rb 控制器,修改為後續渲染頁面

class SettingsController < ApplicationController
    before_action :authenticate_user!
    before_action :set_user

    def show
    end

    def update
       if @user.update(user_params)
            # 後續跳轉到個人設置頁面
            redirect_to root_path
            flash[:notice] = '修改成功'
        else
            render :show
        end
    end
    
    private

    def set_user
      @user = current_user
    end

    def user_params
        params.require(:user).permit(:username, :email, :avatar, :bio)  
    end
end

同樣,視圖也要修改,刪除更改密碼一欄,為什麼呢?因為 devise 中修改密碼,需要輸入原密碼,是很麻煩的,筆者嘗試了一下,放棄了

個人頁

我們繼續做個人頁,也是我們的最後一個頁面,雖然還有很多細節(比如評論、點贊文章、收藏文章等邏輯),但是從頁面的角度講,這就是最後一個頁面了

先建立控制器

rails g controller profile

config/routes.rb 處,新增一個路由映射

get '/:name', to: 'profile#show', as: :profile

前往views/common/_header.html.erb 處,修改原來的 username 視圖

 <li class="nav-item">
    <%= link_to profile_path(current_user.username), class: "nav-link px-2" do %>
      <%= image_tag current_user.avatar, alt: "avatar", class: "user-pic" %>
      <%= current_user.username %>
    <% end %>
  </li>

然後我們去 view/profile/show.html.erb 寫好我們的靜態頁面,7個頁面就此完成,但這隻完成了一半。接下來,我們要對頁面進行改造,加上文章評論、點贊/取消點贊、關注/取消用户等等功能

如此,已經耗盡一天功夫,休息一晚,明天再戰

系列文章

  • 前端學Ruby:前言
  • 前端學 Ruby:安裝Ruby、Rails
  • 前端學 Ruby:熟悉 Ruby 語法
  • 前端學 Ruby:熟悉Rails
  • 前端學 Ruby:唐詩API項目
  • 前端學 Ruby:唐詩項目部署優化
user avatar dingtongya 頭像 cyzf 頭像 vleedesigntheory 頭像 monkeynik 頭像 dirackeeko 頭像 aqiongbei 頭像 longlong688 頭像 dunizb 頭像 eolink 頭像 yian 頭像 b_a_r_a_n 頭像 tizuqiudehongcha 頭像
點贊 60 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.