Zmiana nazwy utworzonych w, zaktualizowanych w kolumnach ActiveRecord/Rails

Chcę zmienić nazwę kolumn timestamp zdefiniowanych w timestamp.rb . Czy metody znacznika czasu.RB być nadpisane? I co należy zrobić w aplikacji, aby moduł z nadpisanymi metodami został użyty.

Author: Rainer Blessing, 2009-04-09

9 answers

Nie ma na to prostego sposobu. Możesz to osiągnąć poprzez nadpisanie modułu ActiveRecord:: Timestamp lub napisanie własnego, aby zrobić za Ciebie magię.

Oto jak działa magia.

 4
Author: Milan Novota,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-09 10:33:01

Można to zrobić poprzez napisanie metody modułu ActiveRecord:: Timestamp. Nie nadpisuje całego modułu. Muszę osiągnąć ten sam cel, ponieważ pracuję ze starszą bazą danych. Jestem na rails 3 i zacząłem podążać za metodologią jak zrobić łatkę mojego kodu z nadpisywaniem funkcjonalności rails.

Najpierw tworzę projekt bazowy, z którym pracuję i tworzę plik o tej nazwie w inicjalizatorach. W tym przypadku stworzyłem active_record.rb. A w pliku umieściłem kod, aby zastąpić dwie metody, które kontrolowały znacznik czasu. Poniżej znajduje się próbka mojego kodu:

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

Uwaga: chciałbym również wspomnieć, że tego rodzaju łatanie małp, aby wszystko działało, jest źle widziane i może pękać na aktualizacjach, więc bądźcie ostrożni i bądźcie w pełni świadomi tego, co chcecie robić.

Aktualizacje:

  • zmiana nazw kolumn znacznika czasu z symbolu na ciąg znaków dla zmiana api. Dzięki. Techbrunch za zwrócenie mojej uwagi na tę zmianę API.
 25
Author: Patelify,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-13 01:27:14

Myślę, że metoda Npatela jest właściwym podejściem, ale robi zbyt wiele, jeśli trzeba tylko zmienić #created_at na jednym modelu. Ponieważ moduł znacznika czasu jest zawarty w każdym obiekcie AR, można go zastąpić dla każdego modelu, a nie globalnie.

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

Rails ~> 5.1

  private_class_method
  def self.timestamp_attributes_for_create
    super << :registered_at
  end
end
 24
Author: Tadas Tamosauskas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-13 12:45:39

Możesz użyć metod beforesave i beforecreate, aby opublikować DateTime.teraz do określonych kolumn.

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
 5
Author: Blaine Kasten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-20 16:04:04

Quick ugly hack, opracowany z odpowiedzi Milana Novoty: Dołącz następujące do środowiska.rb, zastępując wartości stałych CREATED_COL i UPDATED_COL żądanymi nazwami kolumn:


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
 3
Author: Maximiliano Guzman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-09 16:22:13

Poprawna składnia do robienia tego w rails 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
 1
Author: Rahul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-13 09:38:43

LUB możesz po prostu utworzyć własne kolumny (DateTime) i ręcznie ustawić kolumnę created_at podczas tworzenia i ustawić kolumnę updated_at podczas aktualizacji. To może być łatwiejsze niż hack powyżej. To właśnie zrobię. Jeszcze lepiej, zaktualizuj rails, aby umożliwić nam zmianę tych nazw.

 0
Author: ma11hew28,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-09 19:37:55

Sol ' n, który nie używa plastra małpy; użyj reversible blokowanie podczas migracji:

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
Author: unboundev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-02 21:53:15

An zaktualizowano anwser dla Rails >= 5.1 . Sugerowałbym użycie ApplicationRecord, który jest domyślnie dostępny w Twojej aplikacji i zdefiniowanie:

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

Zauważ, że możesz również użyć tego bloku dla określonego modelu, jeśli nie chcesz go skonfigurować dla wszystkich modeli.

Zauważ również, że powinieneś używać łańcuchów, a nie symboli.

 0
Author: coorasse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-11 13:17:35