2009-04-09 3 views

ответ

4

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

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

+2

FYI, ссылка выше для старой версии Rails (2?). Если вы используете Rails 3, см. Ответ NPatel. – Jared

+0

[Здесь] (https://github.com/rails/rails/blob/master/activerecord/lib/active_record/timestamp.rb) модель от ведущей ветки rails – user980085

3

быстро некрасиво хак, конкретизируя от ответа Милана Novota в: добавить следующий 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 
+0

Спасибо, это хорошее решение. –

+0

Rails 3 сделал это решение устаревшим. Проверьте один из @NPatel для обновленного. –

+0

Пожалуйста, прекратите использование патчей обезьян. – sickill

0

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

25

Это можно сделать, просто написав методы модуля 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 в мое внимание.
+0

Отличный совет, спас мой день! –

+0

Пожалуйста, прекратите использование патчей обезьян. – sickill

+1

Этот ответ устарел, вам нужно будет обновить код, так как 'timestamp_attributes_for_ {create, update}' были [изменены с символа на строку] (https://github.com/rails/rails/commit/2b5dacb43dd92e98e1fd240a80c2a540ed380257). – Techbrunch

22

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

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

Просто FYI :)

+0

Это все еще актуально для Rails 5.1? Кажется, он не работает. – zmanw

+1

Этот метод относится к классу вместо экземпляра в Rails 5.1, поэтому теперь он равен 'private_class_method def self.timestamp_attributes_for_create' –

5

Вы можете использовать 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 
+0

Это будет обновлять' created_column' каждый раз, когда вы обновляете запись. –

+0

Исправлено. Благодаря.. –

0

Soln, который не использует патч обезьяны; использовать 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

Правильный синтаксис для этого в рельсах 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 
Смежные вопросы