Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

Ruby on Rails | 全て・有・無を扱うラジオボタンの検索を部品化する

概要

全て・有・無を扱うラジオボタンの検索を部品化する

詳細

全て・有・無を扱うラジオボタンの検索を部品化します。
フラグ系の項目に対して、true・false・その双方を検索するような
要件は多々あると思います。

べた書き版 scope

ユーザーの権限と削除状態を扱う二つの項目の検索を定義する場合、
下記のように重複したコードになります。
※UIにはラジオボタンを利用し、valueにall・true・falseが設定されている前提

Model
  scope :admin_is, lambda {|admin|
    next if admin == "all"
    admin_role = admin == "true" ? true : false
    where(:admin => admin_role)
  }

DRY版

ActiveRecord::Baseを拡張してヘルパーメソッドを追加

conf/initializers/active_record.rb

module ActiveRecord
  class Base
    class << self
      def yes_no_all_search(column_sym)
        lambda {|column|
          next if column == "all"
          column_ = column == "true" ? true : false
          where(column_sym => column_)
        }
      end
    end
  end
end
DRY版 scope
scope :admin_is, yes_no_all_search(:admin)

すっきりしました。これで、他の箇所で同様の機能を利用したくなったら上記の1行を呼び出して引数を
変えるだけになりました。

続いてViewの共通化です。

べた書き版 View

views/user/index.html.haml

%table{:class => 'user_search'}
  %tr 
    %td 
      =label_tag 'login', tara('user', 'login')
    %td 
      =text_field :user, :login
    %td 
      =label_tag 'admin', tara('user', 'admin')
    %td
       %span{:class => "yes_no_all_radio"}
         =t('radio.all')
         =radio_button 'user', 'admin', 'all', {:checked => check_radio_all(:checked => @admin, :default => true)}
       %span{:class => "yes_no_all_radio"}
         =t('radio.yes_')
         =radio_button 'user', 'admin', 'true', {:checked => check_radio_true(:checked => @admin)}
       %span{:class => "yes_no_all_radio"}
         =t('radio.no_')
         =radio_button 'user', 'admin', 'false', {:checked => check_radio_false(:checked => @admin)}
DRY版 View

_yes_no_all_radio.html.haml

- default_all = default == :all ? true : false
- default_yes = default == :yes ? true : false
- default_no = default == :no ? true : false
- on_label = label_type == :yes ? t('radio.yes_') : t('radio.complete')
- off_label = label_type == :yes ? t('radio.no_') : t('radio.not_complete')
%p{:id => "yes_no_all_radio_#{property_name}"}
  %span{:class => "yes_no_all_radio"}
    =t('radio.all')
    =radio_button object_name, property_name, 'all', {:checked => check_radio_all(:checked => checked, :default => default_all)}
  %span{:class => "yes_no_all_radio"}
    =on_label
    =radio_button object_name, property_name, 'true', {:checked => check_radio_true(:checked => checked, :default => default_yes)}
  %span{:class => "yes_no_all_radio"}
    =off_label
    =radio_button object_name, property_name, 'false', {:checked => check_radio_false(:checked => checked, :default => default_no)}

views/user/index.html.haml

%table{:class => 'user_search'}
  %tr 
    %td 
      =label_tag 'login', tara('user', 'login')
    %td 
      =text_field :user, :login
    %td 
      =label_tag 'admin', tara('user', 'admin')
    %td
      = render partial: "yes_no_all_radio", locals: {object_name: "user", property_name: "admin", checked: @admin, default: :all, label_type: :yes}

Viewもすっきりしました。
これで、他の箇所で同様の機能を利用したくなったら上記の1行を呼び出して引数を変えるだけになりました。

画像