Thứ năm, 29/08/2019 | 00:00 GMT+7

Cách tạo tài nguyên lồng nhau cho ứng dụng Ruby on Rails

Ruby on Rails là một khuôn khổ ứng dụng web được viết bằng Ruby cung cấp cho các nhà phát triển một cách tiếp cận phù hợp để phát triển ứng dụng. Làm việc với Rails mang lại cho các nhà phát triển:

  • Các quy ước để xử lý những thứ như định tuyến, dữ liệu trạng thái và quản lý tài sản.
  • Nền tảng vững chắc trong mô hình kiến trúc model-view-controller (MCV), phân tách logic của ứng dụng, nằm trong mô hình, khỏi việc trình bày và định tuyến thông tin ứng dụng.

Khi bạn thêm độ phức tạp vào các ứng dụng Rails của bạn , bạn có thể sẽ làm việc với nhiều mô hình, mô hình này đại diện cho giao diện và logic nghiệp vụ của ứng dụng với database của bạn. Thêm các mô hình liên quan nghĩa là cài đặt các mối quan hệ có ý nghĩa giữa chúng, sau đó ảnh hưởng đến cách thông tin được chuyển tiếp qua bộ điều khiển của ứng dụng của bạn và cách nó được thu thập và trình bày lại cho user thông qua các khung nhìn.

Trong hướng dẫn này, bạn sẽ xây dựng trên một ứng dụng Rails hiện có để cung cấp cho user thông tin thực tế về cá mập. Ứng dụng này đã có một mô hình để xử lý dữ liệu cá mập, nhưng bạn sẽ thêm một tài nguyên lồng ghép cho các bài đăng về cá mập riêng lẻ. Điều này sẽ cho phép user xây dựng một loạt suy nghĩ và ý kiến về từng cá mập.

Yêu cầu

Để làm theo hướng dẫn này, bạn cần :

  • Máy local hoặc server phát triển chạy Ubuntu 18.04. Máy phát triển của bạn phải có user không phải root có quyền quản trị và firewall được cấu hình với ufw . Để biết hướng dẫn về cách cài đặt điều này, hãy xem hướng dẫn Cài đặt server ban đầu với Ubuntu 18.04 của ta .
  • Node.jsnpm được cài đặt trên máy local hoặc server phát triển của bạn. Hướng dẫn này sử dụng Node.js version 10.16.3npm version 6.9.0 . Để biết hướng dẫn về cách cài đặt Node.js và npm trên Ubuntu 18.04, hãy làm theo hướng dẫn trong phần “Cài đặt bằng PPA” của Cách cài đặt Node.js trên Ubuntu 18.04 .
  • Ruby, rbenv và Rails được cài đặt trên máy local hoặc server phát triển của bạn, hãy làm theo các Bước 1-4 trong Cách cài đặt Ruby on Rails với rbenv trên Ubuntu 18.04 . Hướng dẫn này sử dụng Ruby 2.5.1 , rbenv 1.1.2 và Rails 5.2.3 .
  • SQLite đã được cài đặt và một ứng dụng thông tin cá mập cơ bản đã được tạo, theo hướng dẫn trongCách tạo ứng dụngRuby on Rails .

Bước 1 - Dựng mô hình lồng nhau

Ứng dụng của ta sẽ tận dụng các liên kết Active Record để xây dựng mối quan hệ giữa các mô hình SharkPost : các bài đăng sẽ thuộc về các cá mập cụ thể và mỗi cá mập có thể có nhiều bài đăng. Do đó, mô hình SharkPost của ta sẽ có liên quan thông qua các hiệp hội belongs_tohas_many .

Bước đầu tiên để xây dựng ứng dụng theo cách này sẽ là tạo một mô hình Post và các tài nguyên liên quan. Để thực hiện việc này, ta có thể sử dụng lệnh rails generate scaffold , lệnh này sẽ cung cấp cho ta một mô hình, một chuyển đổi database để thay đổi schemas database , một bộ điều khiển, một tập hợp đầy đủ các chế độ xem để quản lý chuẩn Tạo, Đọc, Cập nhật và Xóa (CRUD ) hoạt động và các mẫu cho các phần, trình trợ giúp và kiểm tra. Ta cần phải sửa đổi các tài nguyên này, nhưng sử dụng lệnh scaffold sẽ giúp ta tiết kiệm một số thời gian và năng lượng vì nó tạo ra một cấu trúc mà ta có thể sử dụng làm điểm bắt đầu.

Trước tiên, hãy đảm bảo bạn đang ở trong folder sharkapp cho dự án Rails mà bạn đã tạo trong yêu cầu :

  • cd sharkapp

Tạo tài nguyên Post của bạn bằng lệnh sau:

  • rails generate scaffold Post body:text shark:references

Với body:text , ta đang nói Rails bao gồm một body lĩnh vực trong posts bảng database - bảng mà bản đồ để các Post mô hình. Ta cũng bao gồm :references từ khóa :references , cài đặt mối liên kết giữa mô hình SharkPost . Cụ thể, điều này sẽ đảm bảo một khóa ngoại đại diện cho mỗi mục nhập cá mập trong database sharks được thêm vào database posts .

Khi bạn đã chạy lệnh, bạn sẽ thấy kết quả xác nhận các tài nguyên mà Rails đã tạo cho ứng dụng. Trước khi tiếp tục, bạn có thể kiểm tra file di chuyển database của bạn để xem xét mối quan hệ hiện đang tồn tại giữa các mô hình và bảng database của bạn. Sử dụng lệnh sau để xem nội dung của file , đảm bảo thay thế dấu thời gian trên file di chuyển của bạn cho những gì được hiển thị ở đây:

  • cat db/migrate/20190805132506_create_posts.rb

Bạn sẽ thấy kết quả sau:

Output
class CreatePosts < ActiveRecord::Migration[5.2] def change create_table :posts do |t| t.text :body t.references :shark, foreign_key: true t.timestamps end end end

Như bạn thấy , bảng này bao gồm một cột cho foreign keys cá mập. Khóa này sẽ có dạng model_name _id - trong trường hợp của ta là shark _id .

Rails cũng đã cài đặt mối quan hệ giữa các mô hình ở những nơi khác. Hãy xem mô hình Post mới được tạo bằng lệnh sau:

  • cat app/models/post.rb
Output
class Post < ApplicationRecord belongs_to :shark end

Các belongs_to bộ hiệp hội lập một mối quan hệ giữa các mô hình trong đó một trường hợp duy nhất của mô hình tuyên bố thuộc về một trường hợp duy nhất của mô hình được đặt tên. Trong trường hợp ứng dụng của ta , điều này nghĩa là một bài đăng thuộc về một con cá mập duy nhất.

Ngoài việc cài đặt mối quan hệ này, lệnh rails generate scaffold cũng tạo các tuyến đường và chế độ xem cho các bài đăng, giống như nó đã làm đối với tài nguyên cá mập của ta trong Bước 3 củaCách xây dựng ứng dụng Ruby on Rails .

Đây là một khởi đầu hữu ích, nhưng ta cần phải cấu hình một số định tuyến bổ sung và củng cố liên kết Active Record cho mô hình Shark để mối quan hệ giữa các mô hình và tuyến của ta hoạt động như mong muốn.

Bước 2 - Chỉ định các tuyến và liên kết lồng nhau cho Mô hình mẹ

Rails đã cài đặt kết hợp belongs_to trong mô hình Post của ta , nhờ vào từ khoá :references trong lệnh rails generate scaffold , nhưng để mối quan hệ đó hoạt động bình thường, ta cũng cần chỉ định một liên kết has_many trong mô hình Shark của bạn . Ta cũng cần áp dụng các thay đổi đối với định tuyến mặc định mà Rails đã cung cấp cho ta để biến các tài nguyên đăng trở thành con của các tài nguyên cá mập.

Để thêm liên kết has_many vào mô hình Shark , hãy mở app/models/shark.rb bằng nano hoặc editor bạn quen dùng :

  • nano app/models/shark.rb

Thêm dòng sau vào file để cài đặt mối quan hệ giữa cá mập và bài đăng:

~ / sharkapp / app / models / shark.rb
class Shark < ApplicationRecord   has_many :posts   validates :name, presence: true, uniqueness: true   validates :facts, presence: true end 

Một điều đáng suy nghĩ ở đây là điều gì sẽ xảy ra với các bài đăng khi một con cá mập cụ thể bị xóa. Ta có thể không muốn các bài đăng liên quan đến một con cá mập bị xóa vẫn còn trong database . Để đảm bảo bất kỳ bài đăng nào liên quan đến một con cá mập nhất định đều bị loại bỏ khi con cá mập đó bị xóa, ta có thể bao gồm tùy chọn dependent với liên kết.

Thêm mã sau vào file đảm bảo rằng hành động destroy đối với một con cá mập nhất định sẽ xóa mọi bài đăng liên quan:

~ / sharkapp / app / models / shark.rb
class Shark < ApplicationRecord   has_many :posts , dependent: :destroy   validates :name, presence: true, uniqueness: true   validates :facts, presence: true end 

Khi bạn đã thực hiện xong những thay đổi này, hãy lưu file . Nếu bạn đang sử dụng nano , bạn có thể thực hiện việc này bằng cách nhấn CTRL+X , Y , sau đó ENTER .

Tiếp theo, mở file config/routes.rb của bạn để sửa đổi mối quan hệ giữa các tuyến tài nguyên của bạn:

  • nano config/routes.rb

Hiện tại, file có dạng như sau:

~ / sharkapp / config / route.rb
Rails.application.routes.draw do   resources :posts    resources :sharks    root 'sharks#index'   # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end 

Mã hiện tại cài đặt một mối quan hệ độc lập giữa các tuyến đường của ta , khi những gì ta muốn diễn đạt là mối quan hệ phụ thuộc giữa cá mập và các bài đăng liên quan của chúng.

Hãy cập nhật khai báo tuyến đường của ta để biến :sharks thành cha của :posts . Cập nhật mã trong file để trông giống như sau:

~ / sharkapp / config / route.rb
Rails.application.routes.draw do   resources :sharks do     resources :posts   end   root 'sharks#index'   # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end 

Lưu file khi bạn hoàn tất chỉnh sửa.

Với những thay đổi này, bạn có thể chuyển sang cập nhật trình điều khiển posts của posts .

Bước 3 - Cập nhật Bộ điều khiển Bài đăng

Sự liên kết giữa các mô hình của ta cung cấp cho ta các phương pháp mà ta có thể sử dụng để tạo các version bài đăng mới liên quan đến những con cá mập cụ thể. Để sử dụng các phương pháp này, ta cần thêm chúng vào trình điều khiển bài viết của ta .

Mở file trình điều khiển bài đăng:

  • nano app/controllers/posts_controller.rb

Hiện tại, file có dạng như sau:

~ / sharkapp / controllers / posts_controller.rb
class PostsController < ApplicationController   before_action :set_post, only: [:show, :edit, :update, :destroy]    # GET /posts   # GET /posts.json   def index     @posts = Post.all   end    # GET /posts/1   # GET /posts/1.json   def show   end    # GET /posts/new   def new     @post = Post.new   end    # GET /posts/1/edit   def edit   end    # POST /posts   # POST /posts.json   def create     @post = Post.new(post_params)      respond_to do |format|       if @post.save         format.html { redirect_to @post, notice: 'Post was successfully created.' }         format.json { render :show, status: :created, location: @post }       else         format.html { render :new }         format.json { render json: @post.errors, status: :unprocessable_entity }       end     end   end    # PATCH/PUT /posts/1   # PATCH/PUT /posts/1.json   def update     respond_to do |format|       if @post.update(post_params)         format.html { redirect_to @post, notice: 'Post was successfully updated.' }         format.json { render :show, status: :ok, location: @post }       else         format.html { render :edit }         format.json { render json: @post.errors, status: :unprocessable_entity }       end     end   end    # DELETE /posts/1   # DELETE /posts/1.json   def destroy     @post.destroy     respond_to do |format|       format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }       format.json { head :no_content }     end   end    private     # Use callbacks to share common setup or constraints between actions.     def set_post       @post = Post.find(params[:id])     end      # Never trust parameters from the scary internet, only allow the white list through.     def post_params       params.require(:post).permit(:body, :shark_id)     end end 

Giống như bộ điều khiển cá mập của ta , các phương thức của bộ điều khiển này hoạt động với các thể hiện của lớp Post liên kết. Ví dụ: phương thức new tạo một thể hiện mới của lớp Post , phương thức index lấy tất cả các thể hiện của lớp và phương thức set_post sử dụng findparams để chọn một bài đăng cụ thể theo id . Tuy nhiên, nếu ta muốn các trường hợp bài đăng của bạn được liên kết với các trường hợp cá mập cụ thể, thì ta cần sửa đổi mã này, vì lớp Post hiện đang hoạt động như một thực thể độc lập.

Các sửa đổi của ta sẽ sử dụng hai điều:

  • Các phương thức có sẵn cho ta khi ta thêm các liên kết belongs_tohas_many vào mô hình của bạn . Cụ thể, bây giờ ta có quyền truy cập vào phương thức build nhờ vào liên kết has_many mà ta đã xác định trong mô hình Shark . Phương pháp này sẽ cho phép ta tạo một bộ sưu tập các đối tượng bài đăng được liên kết với một đối tượng cá mập cụ thể, sử dụng foreign keys shark_id tồn tại trong database posts của ta .
  • Các tuyến đường và trình trợ giúp định tuyến có sẵn khi ta tạo tuyến posts lồng nhau. Để có danh sách đầy đủ các tuyến ví dụ có sẵn khi bạn tạo mối quan hệ lồng nhau giữa các tài nguyên, hãy xem tài liệu Rails . Hiện tại, ta sẽ đủ biết rằng đối với mỗi con cá mập cụ thể - ví dụ như sharks/ 1 - sẽ có một lộ trình liên kết cho các bài đăng liên quan đến con cá mập đó: sharks/ 1 /posts . Cũng sẽ có các trình trợ giúp định tuyến như shark_posts_path(@shark)edit_sharks_posts_path(@shark) tham chiếu đến các tuyến lồng nhau này.

Trong file , ta sẽ bắt đầu bằng cách viết một phương thức, get_shark , sẽ chạy trước mỗi hành động trong bộ điều khiển. Phương thức này sẽ tạo một biến cá thể @shark local bằng cách tìm một cá thể cá mập bằng shark_id . Với biến này có sẵn cho ta trong file , có thể liên kết các bài đăng với một con cá mập cụ thể trong các phương thức khác.

Phía trên các phương thức private khác ở cuối file , hãy thêm phương thức sau:

~ / sharkapp / controllers / posts_controller.rb
. . .  private   def get_shark     @shark = Shark.find(params[:shark_id])   end   # Use callbacks to share common setup or constraints between actions. . . .  

Tiếp theo, thêm bộ lọc tương ứng vào đầu file , trước bộ lọc hiện có:

~ / sharkapp / controllers / posts_controller.rb
class PostsController < ApplicationController   before_action :get_shark 

Điều này sẽ đảm bảo get_shark chạy trước mỗi hành động được xác định trong file .

Tiếp theo, bạn có thể sử dụng version @shark này để viết lại phương thức index . Thay vì lấy tất cả các version của lớp Post , ta muốn phương thức này trả về tất cả các version bài đăng được liên kết với một cá thể cá mập cụ thể.

Sửa đổi phương thức index để trông giống như sau:

~ / sharkapp / controllers / posts_controller.rb
. . .   def index     @posts = @shark.posts   end . . . 

Phương pháp new cần một bản sửa đổi tương tự, vì ta muốn một thể hiện bài đăng mới được liên kết với một con cá mập cụ thể. Để làm điều này, ta có thể sử dụng phương thức build , cùng với biến version @shark local của ta .

Thay đổi phương thức new trông như thế này:

~ / sharkapp / controllers / posts_controller.rb
. . .    def new     @post = @shark.posts.build   end . . .  

Phương thức này tạo một đối tượng bài đăng được liên kết với cá thể cá mập cụ thể từ phương thức get_shark .

Tiếp theo, ta sẽ giải quyết phương thức gắn chặt nhất với new : create . Phương thức create thực hiện hai việc: nó xây dựng một version bài đăng mới bằng cách sử dụng các tham số mà user đã nhập vào biểu mẫu new và nếu không có lỗi, nó sẽ lưu version đó và sử dụng trình trợ giúp định tuyến để chuyển hướng user đến nơi họ có thể nhìn thấy bài mới. Trong trường hợp có lỗi, nó sẽ hiển thị lại mẫu new .

Cập nhật phương thức create để trông giống như sau:

~ / sharkapp / controllers / posts_controller.rb
  def create     @post = @shark.posts.build(post_params)          respond_to do |format|          if @post.save               format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully created.' }             format.json { render :show, status: :created, location: @post }          else             format.html { render :new }             format.json { render json: @post.errors, status: :unprocessable_entity }       end     end   end 

Tiếp theo, hãy xem phương pháp update . Phương thức này sử dụng một biến thể hiện @post , biến này không được đặt rõ ràng trong chính phương thức. Biến này đến từ đâu?

Hãy xem các bộ lọc ở đầu file . Bộ lọc before_action thứ hai, được tạo tự động cung cấp câu trả lời:

~ / sharkapp / controllers / posts_controller.rb
class PostsController < ApplicationController   before_action :get_shark   before_action :set_post, only: [:show, :edit, :update, :destroy]   . . . 

Phương thức update (như show , editdestroy ) lấy một biến @post từ phương thức set_post . Phương thức đó, được liệt kê trong phương thức get_shark cùng với các phương thức private khác của ta , hiện có dạng như sau:

~ / sharkapp / controllers / posts_controller.rb
. . .  private . . .    def set_post     @post = Post.find(params[:id])   end . . . 

Để phù hợp với các phương pháp ta đã sử dụng ở những nơi khác trong file , ta cần sửa đổi phương pháp này để @post đề cập đến một trường hợp cụ thể trong bộ sưu tập các bài đăng được liên kết với một con cá mập cụ thể. Hãy ghi nhớ phương pháp build ở đây - nhờ vào các liên kết giữa các mô hình của ta và các phương thức (như build ) có sẵn cho ta nhờ các liên kết đó, mỗi version bài đăng của ta là một phần của bộ sưu tập các đối tượng được liên kết với cá mập cụ thể. Vì vậy, điều hợp lý là khi truy vấn một bài đăng cụ thể, ta sẽ truy vấn bộ sưu tập các bài đăng liên quan đến một con cá mập cụ thể.

Cập nhật set_post để trông giống như sau:

~ / sharkapp / controllers / posts_controller.rb
. . .  private . . .    def set_post     @post = @shark.posts.find(params[:id])   end . . . 

Thay vì tìm một version cụ thể của toàn bộ lớp Post theo id , thay vào đó ta tìm kiếm một id phù hợp trong tập hợp các bài đăng được liên kết với một con cá mập cụ thể.

Với phương thức đó được cập nhật, ta có thể xem các phương thức updatedestroy .

Phương thức update sử dụng biến cá thể @post từ set_post và sử dụng biến này với post_params mà user đã nhập vào biểu mẫu edit . Trong trường hợp thành công, ta muốn Rails đưa user trở lại chế độ xem index của các bài đăng liên quan đến một con cá mập cụ thể. Trong trường hợp có lỗi, Rails sẽ hiển thị lại mẫu edit .

Trong trường hợp này, thay đổi duy nhất mà ta cần thực hiện là đối với câu lệnh redirect_to , để xử lý các cập nhật thành công. Cập nhật nó để chuyển hướng đến shark_post_path(@shark) , điều này sẽ chuyển hướng đến chế độ xem index của các bài đăng của cá mập đã chọn:

~ / sharkapp / controllers / posts_controller.rb
. . .    def update     respond_to do |format|       if @post.update(post_params)         format.html { redirect_to shark_post_path(@shark), notice: 'Post was successfully updated.' }         format.json { render :show, status: :ok, location: @post }       else         format.html { render :edit }         format.json { render json: @post.errors, status: :unprocessable_entity }       end     end   end . . . 

Tiếp theo, ta sẽ thực hiện một thay đổi tương tự đối với phương thức destroy . Cập nhật phương thức redirect_to để chuyển hướng yêu cầu đến shark_posts_path(@shark) trong trường hợp thành công:

~ / sharkapp / controllers / posts_controller.rb
. . .    def destroy     @post.destroy      respond_to do |format|       format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully destroyed.' }       format.json { head :no_content }     end   end . . . 

Đây là thay đổi cuối cùng mà ta sẽ thực hiện. Đến đây bạn có một file trình điều khiển bài viết trông giống như sau:

~ / sharkapp / controllers / posts_controller.rb
class PostsController < ApplicationController   before_action :get_shark   before_action :set_post, only: [:show, :edit, :update, :destroy]    # GET /posts   # GET /posts.json   def index     @posts = @shark.posts   end    # GET /posts/1   # GET /posts/1.json   def show   end    # GET /posts/new   def new     @post = @shark.posts.build   end    # GET /posts/1/edit   def edit   end    # POST /posts   # POST /posts.json   def create     @post = @shark.posts.build(post_params)          respond_to do |format|          if @post.save               format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully created.' }             format.json { render :show, status: :created, location: @post }          else             format.html { render :new }             format.json { render json: @post.errors, status: :unprocessable_entity }       end     end   end    # PATCH/PUT /posts/1   # PATCH/PUT /posts/1.json   def update     respond_to do |format|       if @post.update(post_params)         format.html { redirect_to shark_post_path(@shark), notice: 'Post was successfully updated.' }         format.json { render :show, status: :ok, location: @post }       else         format.html { render :edit }         format.json { render json: @post.errors, status: :unprocessable_entity }       end     end   end    # DELETE /posts/1   # DELETE /posts/1.json   def destroy     @post.destroy     respond_to do |format|       format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully destroyed.' }       format.json { head :no_content }     end   end    private     def get_shark      @shark = Shark.find(params[:shark_id])    end     # Use callbacks to share common setup or constraints between actions.     def set_post       @post = @shark.posts.find(params[:id])     end      # Never trust parameters from the scary internet, only allow the white list through.     def post_params       params.require(:post).permit(:body, :shark_id)     end end 

Bộ điều khiển quản lý cách thông tin được truyền từ các mẫu khung nhìn đến database và ngược lại. Bộ điều khiển của ta hiện phản ánh mối quan hệ giữa mô hình SharkPost của ta , trong đó các bài đăng được liên kết với các cá mập cụ thể. Ta có thể chuyển sang tự sửa đổi các mẫu chế độ xem, đây là nơi user sẽ chuyển đến và sửa đổi thông tin bài đăng về những con cá mập cụ thể.

Bước 4 - Sửa đổi chế độ xem

Bản sửa đổi mẫu chế độ xem của ta sẽ liên quan đến việc thay đổi các mẫu liên quan đến bài đăng và cũng sửa đổi chế độ xem show cá mập của ta , vì ta muốn user xem các bài đăng liên quan đến cá mập cụ thể.

Hãy bắt đầu với mẫu nền tảng cho các bài đăng của ta : một phần form được sử dụng lại trên nhiều mẫu bài đăng. Mở biểu mẫu đó ngay bây giờ:

  • nano app/views/posts/_form.html.erb

Thay vì chỉ chuyển mô hình post cho trình trợ giúp biểu mẫu form_with , ta sẽ chuyển cả mô hình shark và mô hình post , với post được đặt làm tài nguyên con.

Thay đổi dòng đầu tiên của file thành như thế này, phản ánh mối quan hệ giữa cá mập và tài nguyên bài đăng của ta :

~ / sharkapp / views / posts / _form.html.erb
<%= form_with(model: [@shark, post], local: true) do |form| %> . . .  

Tiếp theo, xóa phần liệt kê shark_id của cá mập liên quan, vì đây không phải là thông tin cần thiết trong chế độ xem.

Biểu mẫu đã hoàn thành, hoàn chỉnh với các chỉnh sửa của ta đối với dòng đầu tiên và không có phần shark_id bị xóa, sẽ trông như thế này:

~ / sharkapp / views / posts / _form.html.erb
<%= form_with(model: [@shark, post], local: true) do |form| %>   <% if post.errors.any? %>     <div id="error_explanation">       <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>        <ul>       <% post.errors.full_messages.each do |message| %>         <li><%= message %></li>       <% end %>       </ul>     </div>   <% end %>    <div class="field">     <%= form.label :body %>     <%= form.text_area :body %>   </div>    <div class="actions">     <%= form.submit %>   </div> <% end %> 

Lưu file khi bạn hoàn tất chỉnh sửa.

Tiếp theo, mở chế độ xem index , sẽ hiển thị các bài đăng liên quan đến một con cá mập cụ thể:

  • nano app/views/posts/index.html.erb

Nhờ có rails generate scaffold lệnh, Rails đã tạo ra phần tốt hơn của mẫu, hoàn chỉnh với một bảng hiển thị body lĩnh vực của mỗi bưu chính liên quan của nó shark .

Giống như các mã khác mà ta đã sửa đổi, tuy nhiên, mẫu này coi các bài đăng là các thực thể độc lập, khi ta muốn sử dụng các liên kết giữa các mô hình của ta với các bộ sưu tập và phương thức trợ giúp mà các liên kết này cung cấp cho ta .

Trong phần nội dung của bảng, hãy thực hiện các cập nhật sau:

Đầu tiên, hãy cập nhật post.shark thành post.shark.name , để bảng này sẽ bao gồm trường tên của cá mập liên quan, thay vì xác định thông tin về bản thân đối tượng cá mập:

~ / sharkapp / app / views / posts / index.html.erb
. . .    <tbody>     <% @posts.each do |post| %>       <tr>         <td><%= post.body %></td>         <td><%= post.shark.name %></td> . . .  

Tiếp theo, thay đổi chuyển hướng Show để hướng user đến chế độ xem show cho con cá mập được liên kết, vì họ rất có thể sẽ muốn một cách để chuyển trở lại con cá mập ban đầu. Ta có thể sử dụng biến cá thể @shark mà ta đặt trong bộ điều khiển ở đây, vì Rails làm cho các biến cá thể được tạo trong bộ điều khiển có sẵn cho tất cả các chế độ xem. Ta cũng sẽ thay đổi văn bản cho liên kết từ Show thành Show Shark để user hiểu rõ hơn về chức năng của nó.

Cập nhật dòng này thành sau:

~ / sharkapp / app / views / posts / index.html.erb
. . .    <tbody>     <% @posts.each do |post| %>       <tr>         <td><%= post.body %></td>         <td><%= post.shark.name %></td>         <td><%= link_to 'Show Shark', [@shark] %></td> 

Trong dòng tiếp theo, ta muốn đảm bảo user được định tuyến đúng đường dẫn lồng nhau khi họ chỉnh sửa bài đăng. Điều này nghĩa là thay vì được chuyển hướng đến các posts/ post_id /edit , user sẽ được chuyển hướng đến các sharks/ shark_id /posts/ post_id /edit . Để thực hiện việc này, ta sẽ sử dụng trình trợ giúp định tuyến shark_post_path và các mô hình của ta , mà Rails sẽ coi là URL. Ta cũng sẽ cập nhật văn bản liên kết để làm cho chức năng của nó rõ ràng hơn.

Cập nhật dòng Edit để trông giống như sau:

~ / sharkapp / app / views / posts / index.html.erb
. . .    <tbody>     <% @posts.each do |post| %>       <tr>         <td><%= post.body %></td>         <td><%= post.shark.name %></td>         <td><%= link_to 'Show Shark', [@shark] %></td>         <td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td> 

Tiếp theo, hãy thêm một thay đổi tương tự vào liên kết Destroy , cập nhật chức năng của nó trong chuỗi, đồng thời thêm shark và tài nguyên post của ta :

~ / sharkapp / app / views / posts / index.html.erb
. . .    <tbody>     <% @posts.each do |post| %>       <tr>         <td><%= post.body %></td>         <td><%= post.shark.name %></td>         <td><%= link_to 'Show Shark', [@shark] %></td>         <td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>         <td><%= link_to 'Destroy Post', [@shark, post], method: :delete, data: { confirm: 'Are you sure?' } %></td> 

Cuối cùng, ở cuối biểu mẫu, ta sẽ muốn cập nhật đường dẫn New Post để đưa user đến đường dẫn lồng nhau thích hợp khi họ muốn tạo bài đăng mới. Cập nhật dòng cuối cùng của file để sử dụng trình trợ giúp định tuyến new_shark_post_path(@shark) :

~ / sharkapp / app / views / posts / index.html.erb
. . .  <%= link_to 'New Post', new_shark_post_path(@shark) %> 

Tệp đã hoàn thành sẽ giống như sau:

~ / sharkapp / app / views / posts / index.html.erb
<p id="notice"><%= notice %></p>  <h1>Posts</h1>  <table>   <thead>     <tr>       <th>Body</th>       <th>Shark</th>       <th colspan="3"></th>     </tr>   </thead>    <tbody>     <% @posts.each do |post| %>       <tr>         <td><%= post.body %></td>         <td><%= post.shark.name %></td>         <td><%= link_to 'Show Shark', [@shark] %></td>         <td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>         <td><%= link_to 'Destroy Post', [@shark, post], method: :delete, data: { confirm: 'Are you sure?' } %></td>       </tr>     <% end %>   </tbody> </table>  <br>  <%= link_to 'New Post', new_shark_post_path(@shark) %> 

Lưu file khi bạn hoàn tất chỉnh sửa.

Các chỉnh sửa khác mà ta sẽ thực hiện để đăng lượt xem sẽ không nhiều, vì các lượt xem khác của ta sử dụng một phần form mà ta đã chỉnh sửa. Tuy nhiên, ta sẽ muốn cập nhật các tham chiếu link_to trong các mẫu bài đăng khác để phản ánh một phần những thay đổi mà ta đã thực hiện đối với form .

Mở app/views/posts/new.html.erb :

  • nano app/views/posts/new.html.erb

Cập nhật tham chiếu link_to ở cuối file để sử dụng trình trợ giúp shark_posts_path(@shark) :

~ / sharkapp / app / views / posts / new.html.erb
. . .  <%= link_to 'Back', shark_posts_path(@shark) %> 

Lưu file khi bạn thực hiện xong thay đổi này.

Tiếp theo, mở mẫu edit :

  • nano app/views/posts/edit.html.erb

Ngoài đường dẫn Back , ta sẽ cập nhật Show để phản ánh các tài nguyên lồng nhau của ta . Thay đổi hai dòng cuối cùng của file thành như thế này:

~ / sharkapp / app / views / posts / edit.html.erb
. . .  <%= link_to 'Show', [@shark, @post] %> | <%= link_to 'Back', shark_posts_path(@shark) %> 

Lưu và đóng file .

Tiếp theo, mở mẫu show :

  • nano app/views/posts/show.html.erb

Thực hiện các chỉnh sửa sau đối với các đường dẫn EditBack ở cuối file :

~ / sharkapp / app / views / posts / edit.html.erb
. . . <%= link_to 'Edit', edit_shark_post_path(@shark, @post) %> | <%= link_to 'Back', shark_posts_path(@shark) %> 

Lưu file khi bạn hoàn tất.

Bước cuối cùng, ta sẽ muốn cập nhật chế độ xem show cho các cá mập của bạn để các bài đăng được hiển thị cho từng cá mập. Mở file đó ngay bây giờ:

  • nano app/views/sharks/show.html.erb

Các chỉnh sửa của ta ở đây sẽ bao gồm thêm phần Posts vào biểu mẫu và liên kết Add Post ở cuối file .

Dưới Facts cho một con cá mập được đưa ra, ta sẽ bổ sung thêm một phần mới đó lặp qua mỗi trường hợp trong bộ sưu tập các bài viết liên quan đến cá mập này, xuất ra body của mỗi bài.

Thêm mã sau vào bên dưới phần Facts của biểu mẫu và phía trên các chuyển hướng ở cuối file :

~ / sharkapp / app / views / shark / show.html.erb
. . . <p>   <strong>Facts:</strong>   <%= @shark.facts %> </p>  <h2>Posts</h2> <% for post in @shark.posts %>     <ul>       <li><%= post.body %></li>   </ul> <% end %>  <%= link_to 'Edit', edit_shark_path(@shark) %> | . . .  

Tiếp theo, thêm một chuyển hướng mới để cho phép user thêm bài đăng mới cho con cá mập cụ thể này:

~ / sharkapp / app / views / shark / show.html.erb
. . . <%= link_to 'Edit', edit_shark_path(@shark) %> | <%= link_to 'Add Post', shark_posts_path(@shark) %> | <%= link_to 'Back', sharks_path %> 

Lưu file khi bạn hoàn tất chỉnh sửa.

Đến đây bạn đã áp dụng các thay đổi đối với mô hình, bộ điều khiển và chế độ xem của ứng dụng đảm bảo rằng các bài đăng luôn được liên kết với một con cá mập cụ thể. Bước cuối cùng, ta có thể thêm một số xác thực vào mô hình Post mình đảm bảo tính nhất quán trong dữ liệu được lưu vào database .

Bước 5 - Thêm xác thực và kiểm tra ứng dụng

Trong Bước 5 củaCách xây dựng ứng dụng Ruby on Rails , bạn đã thêm xác thực vào mô hình Shark của bạn đảm bảo tính đồng nhất và nhất quán trong dữ liệu được lưu vào database sharks . Bây giờ ta sẽ thực hiện một bước tương tự đảm bảo tính bảo đảm cho database posts .

Mở file nơi mô hình Post của bạn được xác định:

  • nano app/models/post.rb

Ở đây, ta muốn đảm bảo các bài đăng không trống và chúng không trùng lặp nội dung mà user khác có thể đã đăng. Để làm điều này, hãy thêm dòng sau vào file :

~ / sharkapp / app / models / post.rb
class Post < ApplicationRecord   belongs_to :shark   validates :body, presence: true, uniqueness: true end 

Lưu file khi bạn hoàn tất chỉnh sửa.

Với sự thay đổi cuối cùng này, bạn đã sẵn sàng chạy quá trình di chuyển của bạn và thử nghiệm ứng dụng.

Trước tiên, hãy chạy quá trình di chuyển của bạn:

  • rails db:migrate

Tiếp theo, khởi động server của bạn. Nếu bạn đang làm việc tại local , bạn có thể thực hiện bằng cách chạy:

  • rails s

Nếu bạn đang làm việc trên server phát triển, hãy chạy lệnh sau để thay thế:

  • rails s --binding=your_server_ip

Điều hướng đến folder root của ứng dụng của bạn tại http://localhost:3000 hoặc http:// your_server_ip :3000 .

Hướng dẫn dự án Rails tiên quyết đã hướng dẫn bạn cách thêm và chỉnh sửa một mục nhập Great White shark. Nếu bạn không thêm bất kỳ cá mập nào nữa, trang đích của ứng dụng sẽ trông như thế này:

Trang đích ứng dụng Shark

Nhấp vào Hiển thị bên cạnh tên của Great White . Điều này sẽ đưa bạn đến chế độ xem show cho con cá mập này. Bạn sẽ thấy tên của cá mập và sự thật của nó, và tiêu đề Bài đăng không có nội dung. Hãy thêm một bài đăng để điền phần này của biểu mẫu.

Nhấp vào Thêm Bài đăng bên dưới tiêu đề Bài đăng . Thao tác này sẽ đưa bạn đến chế độ xem index bài đăng, nơi bạn sẽ có cơ hội chọn Bài đăng mới :

Bài đăng Xem index

Nhờ các cơ chế xác thực bạn đã đặt trong Bước 6 củaCách xây dựng ứng dụng Ruby on Rails , bạn có thể được yêu cầu xác thực bằng tên user và password mà bạn đã tạo trong Bước đó, tùy thuộc vào việc bạn có tạo phiên mới hay không. .

Nhấp vào Bài đăng mới , sẽ đưa bạn đến bài đăng của bạn mẫu new :

Bài viết mới

Trong trường Body , nhập, "Những con cá mập này thật đáng sợ!"

Bài Shark mới

Nhấp vào Tạo bài đăng . Bạn sẽ được chuyển hướng đến chế độ xem index cho tất cả các bài viết thuộc về cá mập này:

Đăng thành công

Với các tài nguyên bài đăng của ta đang hoạt động, giờ đây ta có thể kiểm tra xác thực dữ liệu của bạn đảm bảo rằng chỉ dữ liệu mong muốn mới được lưu vào database .

Từ chế độ xem index , nhấp vào Bài đăng mới . Trong trường Body của biểu mẫu mới, hãy thử nhập "Những con cá mập này thật đáng sợ!" lần nữa:

Lặp lại bài Shark

Nhấp vào Tạo bài đăng . Bạn sẽ thấy lỗi sau:

Lỗi bài đăng duy nhất

Nhấp vào Quay lại để quay lại trang bài viết chính.

Để kiểm tra xác nhận khác của ta , hãy nhấp lại vào Bài đăng mới . Để trống bài đăng và nhấp vào Tạo bài đăng . Bạn sẽ thấy lỗi sau:

Lỗi bài đăng trống

Với các tài nguyên và xác thực lồng nhau của bạn hoạt động bình thường, giờ đây bạn có một ứng dụng Rails đang hoạt động mà bạn có thể sử dụng làm điểm khởi đầu để phát triển thêm.

Kết luận

Với ứng dụng Rails của bạn, bây giờ bạn có thể làm việc với những thứ như tạo kiểu và phát triển các thành phần front-end khác. Nếu bạn muốn tìm hiểu thêm về định tuyến và tài nguyên lồng nhau, tài liệu Rails là một nơi tuyệt vời để bắt đầu.

Để tìm hiểu thêm về cách tích hợp các khuôn khổ front-end với ứng dụng của bạn, hãy xem Cách cài đặt một dự án Ruby on Rails với một React Frontend .


Tags:

Các tin liên quan