Переименование столбцов create_at, updated_at в ActiveRecord / Rails - PullRequest
13 голосов
/ 09 апреля 2009

Я хочу переименовать столбцы меток времени, определенные в timestamp.rb. Можно ли переписать методы timestamp.rb? И что нужно сделать в приложении, чтобы использовался модуль с перезаписанными методами.

Ответы [ 9 ]

25 голосов
/ 20 октября 2010

Это можно сделать, просто переписав методы модуля ActiveRecord :: Timestamp. На самом деле не перезаписывает весь модуль. Мне нужно для достижения этой же цели, так как я работаю с устаревшей базой данных. Я нахожусь на рельсах 3, и я начал следовать методологии, как обезопасить мой код с перезаписью функциональности рельсов.

Сначала я создаю базовый проект, с которым я работаю, и создаю файл с именем этого в инициализаторах. В этом случае я создал active_record.rb. И внутри файла я поместил код для переопределения двух методов, которые контролировали метку времени. Ниже приведен пример моего кода:

module ActiveRecord
    module Timestamp      
      private
      def timestamp_attributes_for_update #:nodoc:
        ["updated_at", "updated_on", "modified_at"]
      end
      def timestamp_attributes_for_create #:nodoc:
        ["created_at", "created_on"]
      end      
    end
  end

ПРИМЕЧАНИЕ: Я также хотел бы отметить, что такого рода исправления обезьян, чтобы заставить вещи работать, не одобряются и могут нарушать обновления, поэтому будьте осторожны и полностью осознайте, что вы хотите делать.

Обновление:

  • Изменить имена столбцов меток времени с символа на строку в соответствии с api change . Спасибо Techbrunch за привлечение внимания к этим изменениям API.
24 голосов
/ 19 ноября 2012

Я думаю, что метод NPatel является правильным подходом, но он делает слишком много, если вам нужно только изменить #created_at в одной модели. Поскольку модуль Timestamp включен в каждый объект AR, вы можете просто переопределить его для каждой модели, а не глобально.

<= Rails 5.0 </p>

class User < ActiveRecord::Base
  ...
  private
  def timestamp_attributes_for_create
    super << :registered_at
  end
end

Рельсы ~> 5.1

  private_class_method
  def self.timestamp_attributes_for_create
    # only strings allowed here, symbols won't work, see below commit for more details
    # https://github.com/rails/rails/commit/2b5dacb43dd92e98e1fd240a80c2a540ed380257 
    super << 'registered_at' 
  end
end
5 голосов
/ 13 августа 2013

Вы можете использовать методы beforesave и beforecreate для отправки DateTime.now в указанные вами столбцы.

class Sample < ActiveRecord::Base
  before_create :set_time_stamps
  before_save :set_time_stamps

  private
  def set_time_stamps
    self.created_column = DateTime.now if self.new_record?
    self.updated_column = DateTime.now
  end
end
4 голосов
/ 09 апреля 2009

Нет простого способа сделать это. Вы можете сделать это либо переопределив модуль ActiveRecord :: Timestamp, либо написав свой собственный, чтобы сделать магию за вас.

Вот как работает магия.

3 голосов
/ 09 апреля 2009

быстрый уродливый взлом, исходя из ответа Милана Новоты: добавьте следующее к environment.rb, заменив значения констант CREATED_COL и UPDATED_COL на нужные имена столбцов:


module ActiveRecord
  module Timestamp
    CREATED_COL = 'created_at'
    UPDATED_COL = 'updated_at'
    private
      def create_with_timestamps #:nodoc:
        if record_timestamps
          t = self.class.default_timezone == :utc ? Time.now.utc : Time.now
          write_attribute(CREATED_COL, t) if respond_to?(CREATED_COL) && send(CREATED_COL).nil?
          write_attribute(UPDATED_COL, t) if respond_to?(UPDATED_COL) && send(UPDATED_COL).nil?
        end
        create_without_timestamps
      end

      def update_with_timestamps(*args) #:nodoc:
        if record_timestamps && (!partial_updates? || changed?)
          t = self.class.default_timezone == :utc ? Time.now.utc : Time.now
          write_attribute(UPDATED_COL, t) if respond_to?(UPDATED_COL)
        end
        update_without_timestamps(*args)
      end
  end
end
1 голос
/ 11 сентября 2018

Обновленный ответ для Rails> = 5.1 . Я бы предложил использовать ApplicationRecord, который доступен по умолчанию в вашем приложении, и определить следующее:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  class << self
    private

    def timestamp_attributes_for_create
      super << 'my_created_at_column'
    end

    def timestamp_attributes_for_update
      super << 'my_updated_at_column'
    end
  end
end

Обратите внимание , что вы также можете использовать этот блок для конкретной модели, если не хотите настраивать его для всех своих моделей.

Обратите внимание также, что вы должны использовать строки, а не символы.

1 голос
/ 13 февраля 2018

Правильный синтаксис для этого в рельсах 4.2

class User < ActiveRecord::Base
...

private

    def timestamp_attributes_for_create
        super << 'date_add'
    end

    def timestamp_attributes_for_update
        super << 'date_update'
    end
end
0 голосов
/ 03 августа 2015

Sol'n, который не использует патч обезьяны; используйте блок reversible во время миграции:

class CreateTest < ActiveRecord::Migration
  def change

    create_table :test do |t|
    end

    # set the timestamp columns default to now()
    reversible do |dir|
      dir.up do
        tables = [
          :test
        ]
        tables.each do |t|
          execute <<-SQL
            ALTER TABLE #{t.to_s}
              add column created timestamp without time zone default now();
          SQL
          execute <<-SQL
            ALTER TABLE #{t.to_s}
              add column updated timestamp without time zone default now();
          SQL
        end
      end
      dir.down do
        # no need to do anything, the rollback will drop the tables
      end
    end

  end
end
0 голосов
/ 09 июля 2010

Или вы можете просто создать свои собственные столбцы (DateTime) и просто вручную установить столбец create_at при создании и установить столбец updated_at при обновлении. Это может быть проще, чем взломать выше. Это то, что я собираюсь сделать. А еще лучше, обновите рельсы, чтобы мы могли изменить эти имена.

...