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_to
vàhas_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ứcbuild
nhờ vào liên kếthas_many
mà 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_id
tồn tại trong databaseposts
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)
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