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.js và npm đượ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.3 và npm 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 Shark và Post : 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 Shark và Post của  ta  sẽ có liên quan thông qua các hiệp hội belongs_to và has_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 Shark và Post . 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:
Outputclass 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 
Outputclass 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:
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:
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:
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:
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:
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 find và params để 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_tovàhas_manyvà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ứcbuildnhờ vào liên kếthas_manymà ta đã xác định trong mô hìnhShark. 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 keysshark_idtồn tại trong databasepostscủ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 postslồ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)và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:
. . .  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ó:
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:
. . .   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:
. . .    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:
  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:
class PostsController < ApplicationController   before_action :get_shark   before_action :set_post, only: [:show, :edit, :update, :destroy]   . . . Phương thức update (như show , edit và destroy ) 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:
. . .  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:
. . .  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 update và destroy .
 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:
. . .    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:
. . .    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:
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 Shark và Post 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 :
<%= 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:
<%= 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:
. . .    <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:
. . .    <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:
. . .    <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 :
. . .    <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) :
. . .  <%= link_to 'New Post', new_shark_post_path(@shark) %> Tệp đã hoàn thành sẽ giống như sau:
<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) :
. . .  <%= 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:
. . .  <%= 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 Edit và Back ở cuối file :
. . . <%= 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 :
. . . <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:
. . . <%= 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 :
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:
 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 : 
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 : 
Trong trường Body , nhập, "Những con cá mập này thật đáng sợ!"
 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: 
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: 
Nhấp vào Tạo bài đăng . Bạn sẽ thấy lỗi sau:
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:
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 .
Các tin liên quan
 

