7-1 情境和 Model 准备
这一章我们同样示范如何在表单实作一个单选的UI,例如活动(Event)需要一个分类,但是跟上一章是固定有限的选项不同,我们希望分类是可以持续编辑的,因此需要再新增一个Category Model,然后让Category has_many Event 来建立数据关系。
执行bin/rails g model category name:string
编辑db/migrate/<timestamp>_create_categories.rb
class CreateCategories < ActiveRecord::Migration[5.0]
def change
create_table :categories do |t|
t.string :name
t.timestamps
end
+ add_column :events, :category_id, :integer
+ add_index :events, :category_id
end
end
执行bin/rails db:migrate
编辑 app/models/category.rb 加上关联:
class Category < ApplicationRecord
+ has_many :events
end
编辑 app/models/event.rb 加上关联:
class Event < ApplicationRecord
+ belongs_to :category, :optional => true
针对Category model 的CRUD 接口这里就省略了,你可以通过 bin/rails g controller admin::categories 盖一个后台去编辑。
请直接进 bin/rails console 手动加一些分类:
10.times{ |i| Category.create!( :name => "#{i} Category" ) }
7-2 使用Select 下拉选单
接着来编辑后台表单,在编辑活动时,可以选择分类。
编辑app/views/admin/events/_form.html.erb
+ <div class="form-group">
+ <%= f.label :category_id %>
+ <%= f.select :category_id, Category.all.map{ |c| [c.name, c.id] }, {}, :class => "form-control" %>
+ </div>
如果你用simple_form而不是Rails 内建的
form_for来制作表单的话,是写<%= f.association :category %>效果是一样的。
编辑app/controllers/admin/events_controller.rb
def event_params
- params.require(:event).permit(:name, :description, :friendly_id, :status)
+ params.require(:event).permit(:name, :description, :friendly_id, :status, :category_id)
end
7-3 显示分类并避免nil 错误
在前台的活动页面,需要显示该活动的分类。
编辑app/views/events/show.html.erb
+ <h2><%= @event.category.name %></h2>
活动的 category_id 是后来才增加的字段,因此有些活动是没有 category_id 资料的。这时如果我们去点其他还没有选分类的活动,会发现出现以下的错误:
这是因为 @event.category 是nil,再调用 nil.name 就会出现 NoMethodError 了。
针对这种情况,Rails 提供了一个 try 方法,参数就是要调用的方法名称。透过 try 不管是不是nil,都不会报错:
- <h2><%= @event.category.name %></h2>
+ <h2><%= @event.category.try(:name) %></h2>
这样就算没有选Cateogry 也不会报错了