LoginSignup
0
0

More than 3 years have passed since last update.

rails_admin で alias_attribute な enum を扱えるようにする

Posted at

前段

enum layout: { list: 0, grid: 1 }

上記のような top_layoutinteger のような enum があったとして、それを top_layout という名前に変えたいとします。(カラムのリネームが一番良いというのは置いておいて)

アプリケーションで扱う上では、以下のように alias_attributeenum の変更で事足りました。

alias_attribute :top_layout, :layout

enum top_layout: { list: 0, grid: 1 }

一方で、 rails_admin が生成する UI の方は依然として layout が表示され、 top_layout が現れません。

rails_admin が ActiveRecord の属性をどう取得しているか

adapters/active_recored.rb
module RailsAdmin
  module Adapters
    module ActiveRecord
      def properties
        columns = model.columns.reject do |c|
          c.type.blank? ||
            DISABLED_COLUMN_TYPES.include?(c.type.to_sym) ||
            c.try(:array)
        end
        columns.collect do |property|
          Property.new(property, model)
        end
      end

ざっと見ただけなので、他にも関連する要素はあるかもしれませんが、この properties で生成されたものをベースに扱っているように見えます。

これを確認したい場合には、console を開いて以下で確認できます。

> c = RailsAdmin.config(SampleModel.first)
> c.abstract_model.properties

当然 columns を取得されると、 alias_attribute したところでどうしようもないです。

カスタマイズする

config/initializer/rails_admin.rb
RailsAdmin.config do |config|
  config.model SampleModel do
    include_all_fields
    exclude_fields :layout

    field :top_layout, :active_record_enum
  end

Wiki に従い、無効にしたい layoutexlude_fields に入れ、新たに入れたい top_layout を追加し、 active_record_enum として登録しました。

これで、通常の enum カラムと同じように表示されるようになります。

更新時に失敗する

このままだと、更新時になぜか 0, 1 といった値が、 enum の値として認識されず、「'0' のような値は enum には存在しない」といったエラーが出てしまいます。

ここに関しては以下が関わっています。

config/fields/types/active_record_enum.rb
module RailsAdmin
  module Config
    module Fields
      module Types
        class ActiveRecordEnum < Enum
          def parse_input_value(value)
            abstract_model.model.attribute_types[name.to_s].deserialize(value)
          end

この abstract_model.model でアプリケーション側のモデル(例えば SampleModel)を参照しているので、 attribute_typesSampleModel.attribute_types などすれば確認できます。

確認するとわかりますが、alias_attribute するだけでは、この一覧に top_layout は入ってきません。よって、ここでの deserialize は何も変化がなく、リクエストパラメーターとして送信された '0'という文字列がそのまま assign_attributes に渡されてしまい、上述のエラーになってしまいます。

attribute を定義する

attribute :top_layout, :integer

このような形で top_layout も attribute として定義を追加します。ここは ActiveRecord::Enum::EnumType を直接指定できるような type を与えたいところですが、それはできないので integer にします。これは、もともとの layout の型と同じです。

ここで attribute_types を実行するとわかりますが、alias_attribute 後も layout は ActiveRecord::Enum::EnumType として存在し続け、 top_layout は integer として定義されたような形になります。top_layout の enum 定義が、そのまま alias のオリジナルの layout の方にかかる形になるようです。

これで、更新時にも値の型変換が行われるようになったため、更新も問題なくできるようになりました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0