【Rails 应用实战】7. 表单单选(有Model)

103 阅读1分钟

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 也不会报错了