Single Table Inheritance trong Rails 4 (Phần3)
Bài đăng này đã không được cập nhật trong 8 năm
Trong bài viết trước, chúng tôi đã hướng dẫn việc tạo controller chung và xác định view index. Trong bài này, chúng tôi sẽ bổ sung thêm các view còn thiếu và thấy một số thủ thuật để xử lý đường dẫn cho các model STI.
Tạo các đường dẫn động trong file helpers
Trước khi thêm các view khác, ta cần tạo ra các đường dẫn động dựa theo race
. Để làm điều đó, chúng ta có thể sử dụng các method sau trong helpers.
# helpers/animals_helper.rb
# Returns a dynamic path based on the provided parameters
def sti_animal_path(race = "animal", animal = nil, action = nil)
send "#{format_sti(action, race, animal)}_path", animal
end
def format_sti(action, race, animal)
action || animal ? "#{format_action(action)}#{race.underscore}" : "#{race.underscore.pluralize}"
end
def format_action(action)
action ? "#{action}_" : ""
end
** Tạo đường dẫn và file view cho action show**
Update index.html
với method mới này:
<td><%= link_to 'Show', sti_animal_path(animal.race, animal) %></td>
Và tạo ra file show.html.erb
trong views/animals:
<h1>Hi, I'm a <%= @animal.race %>.</h1>
<p>My name is <%= @animal.name %></p>
<%= @animal.talk %>
Bước cuối cùng, chúng ta cần phải xác định @animal
trong controller. Để làm điều đó, chúng ta sẽ thêm before_action
gọi lại trước mỗi action mà chúng ta cần xác định @animal:
class AnimalsController < ApplicationController
before_action :set_animal, only: [:show, :edit, :update, :destroy]
before_action :set_race
def index
@animals = race_class.all
end
def show
end
# Code hidden for brivety
private
# Code hidden for brivety
def set_animal
@animal = race_class.find(params[:id])
end
end
Bây giờ refresh lại trang, click vào show! Nó sẽ chuyển đến trang show đúng loại animal tương ứng với đường đẫn (lions/meerkats/wild_boars).
Thêm đường dẫn trong index view
Bổ sung thêm một số đường dẫn đến danh sách từng loại animal vào trang index:
<td><%= link_to "See all #{animal.race.pluralize}", sti_animal_path(animal.race) %></td>
Và đường dẫn để hiển thị danh sách của tất cả các loại animal:
[...]
</tbody>
</table>
<%= link_to 'See all animals', sti_animal_path %>
Cuối cùng, chúng ta cần một link để tạo animal:
[...]
<%= link_to 'See all animals', sti_animal_path %>
<%= link_to "New #{@race}", sti_animal_path(@race, nil, :new) %>
Hãy test một chút với những gì bạn vừa làm được ^^
Tạo Animal
View cho trang new khá đơn giản, tất cả các logic sẽ được thiết lập trong partial form:
# views/animals/new.html.erb
<h1>New <%= "#{@race.capitalize}" %></h1>
<%= render 'form' %>
<%= link_to 'Back', sti_animal_path(@race) %>
Ngoài ra, chúng ta cần tạo thêm action new trong animals_controller:
# controllers/animals_controller.rb
def new
@animal = race_class.new
end
_form.rb
:
<%= form_for(@animal) do |f| %>
<% if @animal.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@animal.errors.count, "error") %> prohibited this animal from being saved:</h2>
<ul>
<% @animal.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :race %><br>
<%= f.select :race, Animal.races.map {|r| [r.humanize, r.camelcase]}, {}, disabled: @race != "Animal" %>
</div>
<div class="field">
<%= f.label :age %><br>
<%= f.text_field :age %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Bây giờ chúng ta có thể tạo được animal. Select_box race chỉ enabled khi bạn tạo Animal, còn nếu bạn tạo một Lion (/lions/new) thì select_box sẽ được thiết lập giá trị mặc định là lion và disabled.
Strong parameters Animal
Bạn có thể thấy trong đoạn code dưới đây, chúng tôi đã thêm một method để xác định các params cho phép tạo cho model Animal. Action create cũng được thafAnimalory đổi:
class AnimalsController < ApplicationController
# Code hidden for brievety
def create
@animal = Animal.new(animal_params)
if @animal.save
redirect_to @animal, notice: "#{race} was successfully created."
else
render action: 'new'
end
end
# Code hidden for brievety
private
# Code hidden for brievety
def animal_params
params.require(race.underscore.to_sym).permit(:name, :race, :age)
end
end
Thêm action update and delete
Đầu tiên, sẽ đặt các đường dẫn để dễ dàng truy cập các action:
<td><%= link_to 'Edit', sti_animal_path(animal.race, animal, :edit) %></td>
<td><%= link_to 'Destroy', sti_animal_path(animal.race, animal), method: :delete, data: { confirm: 'Are you sure?' } %></td>
Sau đó, chúng tôi xác định các action trong controller:
def update
if @animal.update(animal_params)
redirect_to @animal, notice: "#{race} was successfully created."
else
render action: 'edit'
end
end
def destroy
@animal.destroy
redirect_to animals_url
end
Cuối cùng là thêm file edit.html.erb :
#views/animals/edit.html.erb
<h1>Editing <%= "#{@race}" %></h1>
<%= render 'form' %>
<%= link_to 'Back', sti_animal_path(@race) %>
Kết:
Thông qua hướng dẫn này, tôi hy vọng bạn hiểu những gì có thể được thực hiện với Single Table Inheritance và làm thế nào nó có thể giúp bạn hạn chế sử dụng các controller tương tự nhau.
Tài liệu dịch: https://samurails.com/tutorial/single-table-inheritance-with-rails-4-part-3/
Link dịch phần 1: https://viblo.asia/march_vu/posts/pVYRPJZkG4ng
Link dịch phần 2: https://viblo.asia/march_vu/posts/WkwGnWq3v75g
All rights reserved