モデルのコールバックを使う

元記事はこちら

翻訳

Bad Smell

<% form_for @post do |f| %>
  <%= f.text_field :content %>
  <%= check_box_tag 'auto_tagging' %>
<% end %>

class PostsController < ApplicationController
  def create
    @post = Post.new(params[:post])

    if params[:auto_tagging] == '1'
      @post.tags = AsiaSearch.generate_tags(@post.content)
    else
      @post.tags = ""
    end

    @post.save
  end
end

上記の例では、ユーザーがauto_taggingチェックボックスをクリックしていた場合に、postの内容に従ってtagsを生成し、保存前にpostにtagsの値をセットします。モデルのコールバックを使えば、tagsの値をセットする処理をモデルに移動できます。

Refactor

class Post < ActiveRecord::Base
  attr_accessor :auto_tagging
  before_save :generate_tagging

  private
  def generate_taggings
    return unless auto_tagging == '1'
    self.tags = Asia.search(self.content)
  end
end

<% form_for @post do |f| %>
  <%= f.text_field :content %>
  <%= f.check_box :auto_tagging %>
<% end %>

class PostsController < ApplicationController
  def create
    @post = Post.new(params[:post])
    @post.save
  end
end

上記の通り、before_saveコールバックで、ユーザーがauto_taggingをクリックしていた場合にtagsを生成して、値をセットするPostモデルのgenerate_taggingを作成しました。これでPostsControllerでモデルロジックを気にする必要がなくなりました。

感想

before_saveうまく使えるとコントローラーのロジックをぐっと減らせるので便利。