少於 1 分鐘閱讀

情境

開發專案時常有通用的欄位要新增, 不只 created_at update_at, 還想要加入一些 created_user、updated_user、status、comment 之類的欄位 又不想要每次產生 migration 再重複寫一次

處理方式 - override原有程式碼

新增 schema_definitions.rb 到 initializers

module ActiveRecord
  module ConnectionAdapters
    class TableDefinition
       def timestamps(**options)
        options[:null] = false if options[:null].nil?

        column(:status,  :integer, default: 1, null: false)
        column(:comment, :text, options)
        column(:created_user, :integer, options)
        column(:created_at,   :datetime, options)
        column(:updated_user, :integer, options)
        column(:updated_at,   :datetime, options)
      end
    end
  end
end

如此在 migration 之中的 t.timestamps 就會自動產生 status、comment、created_user、created_at、updated_user、updated_at 這些欄位

補充說明

當然也可以自行增加 action

module ActiveRecord
  module ConnectionAdapters
    class TableDefinition
      def commons(**options)
        options[:null] = false if options[:null].nil?

        column(:status,  :integer, default: 1, null: false)
        column(:comment, :text, options)
      end
    end
  end
end

這樣在 Migration 中加入

class CreateHelloworlds < ActiveRecord::Migration[5.2]
  def change
    create_table :helloworlds do |t|
      t.string :column1
      t.string :column2

      t.commons
      t.timestamps
    end
  end
end

就相當於寫

class CreateHelloworlds < ActiveRecord::Migration[5.2]
  def change
    create_table :helloworlds do |t|
      t.string :column1
      t.string :column2

      t.integer :status, default: 1, null: false
      t.text :comment
      t.timestamps
    end
  end
end

如果想要自動回寫 created_user update_user 可以參考 [Rails] model 中取得 current_user 這篇 並且加入以下程式碼

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
  before_create :create_common_columns
  before_update :update_common_columns
  
  private

  def create_common_columns
    return if User.current.nil?
    self.created_user = User.current.id if self.attributes.include?('created_user')
    self.updated_user = User.current.id if self.attributes.include?('updated_user')
  end

  def update_common_columns
    return if User.current.nil?
    self.updated_user = User.current.id if self.attributes.include?('updated_user')
  end

end

參考

  1. https://github.com/rails/rails/blob/b2eb1d1c55a59fee1e6c4cba7030d8ceb524267c/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb

更新時間:

留言