2009-04-09 33 views

Trả lời

4

Không có cách nào đơn giản để làm điều đó. Bạn có thể thực hiện việc này bằng cách ghi đè mô-đun ActiveRecord :: Timestamp hoặc bằng cách viết mô-đun của riêng bạn để thực hiện phép thuật cho bạn.

Here is cách hoạt động của phép thuật.

+2

FYI, liên kết ở trên dành cho phiên bản cũ hơn của Rails (2?). Nếu bạn đang sử dụng Rails 3, hãy xem câu trả lời của NPatel. – Jared

+0

[Ở đây] (https://github.com/rails/rails/blob/master/activerecord/lib/active_record/timestamp.rb) mô hình từ đường ray master branch – user980085

3

nhanh chóng xấu xí hack, xây dựng từ câu trả lời Milan Novota của: thêm dòng sau vào environment.rb, thay thế các giá trị của CREATED_COL và UPDATED_COL hằng với tên cột mong muốn:


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

Cảm ơn, đây là một giải pháp tốt. –

+0

Rails 3 khiến giải pháp này lỗi thời. Kiểm tra một từ @NPatel cho một cập nhật. –

+0

Vui lòng ngừng sử dụng vá khỉ. – sickill

0

Hoặc bạn chỉ có thể làm cho bạn các cột riêng (DateTime) và chỉ đặt thủ công cột created_at khi bạn tạo và thiết lập cột updated_at khi bạn cập nhật. Điều đó có thể dễ dàng hơn việc hack ở trên. Đó là những gì tôi sẽ làm. Tốt hơn, hãy cập nhật đường ray để cho phép chúng tôi thay đổi các tên này.

25

Điều này có thể được thực hiện thông qua chỉ bằng cách viết các phương thức mô-đun ActiveRecord :: Dấu thời gian. Không thực sự ghi đè toàn bộ mô-đun. Tôi cần phải hoàn thành mục tiêu này khi tôi đang làm việc với một cơ sở dữ liệu cũ. Tôi đang trên đường ray 3 và tôi đã bắt đầu theo một phương pháp làm thế nào để khỉ vá mã của tôi bằng cách viết chức năng đường ray.

Lần đầu tiên tôi tạo dự án cơ sở mà tôi đang làm việc và tạo một tệp được gọi là trong trình khởi tạo. Trong trường hợp này tôi đã tạo active_record.rb. Và trong tập tin tôi đặt mã để ghi đè lên hai phương pháp kiểm soát dấu thời gian. Dưới đây là các mẫu mã của tôi:

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 

LƯU Ý: Tôi cũng muốn đề cập đến loại này của khỉ vá để có được điều cần làm việc không được tán thành và có thể phá vỡ vào nâng cấp vì vậy hãy cẩn thận và hoàn toàn nhận thức được điều bạn muốn làm.

Cập nhật:

  • Thay đổi tên cột timestamp từ biểu tượng để chuỗi mỗi api change. Cảm ơn Techbrunch đã đưa sự thay đổi API này đến sự chú ý của tôi.
+0

Mẹo hay, đã cứu ngày của tôi! –

+0

Vui lòng ngừng sử dụng vá khỉ. – sickill

+1

Câu trả lời này đã lỗi thời, bạn sẽ cần phải cập nhật mã vì 'timestamp_attributes_for_ {create, update}' đã được [thay đổi từ biểu tượng thành chuỗi] (https://github.com/rails/rails/commit/2b5dacb43dd92e98e1fd240a80c2a540ed380257). – Techbrunch

22

Tôi nghĩ rằng phương pháp của NPatel là một cách tiếp cận đúng, nhưng đang làm quá nhiều trong trường hợp bạn chỉ cần thay đổi #created_at trên một mô hình duy nhất. Vì mô-đun Dấu thời gian được bao gồm trong mọi đối tượng AR, bạn chỉ có thể ghi đè mô-đun đó cho mỗi mô hình, chứ không phải trên toàn cầu. Nói:

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

Chỉ cần một FYI :)

+0

Điều này vẫn còn hợp lệ cho Rails 5.1? Nó dường như không hoạt động. – zmanw

+1

Phương pháp này thuộc về lớp thay vì một cá thể trong Rails 5.1, vì vậy bây giờ nó là 'private_class_method def self.timestamp_attributes_for_create' –

5

Bạn có thể sử dụng và phương pháp beforesave beforecreate để đăng DateTime.now vào các cột bạn chỉ định.

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

Điều này sẽ cập nhật' created_column' mỗi khi bạn cập nhật bản ghi –

+0

Cố định. Cảm ơn.. –

0

Một sol'n không sử dụng miếng vá khỉ; sử dụng khối reversible trong khi di chuyển của bạn:

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

Cú pháp chính xác để thực hiện điều này trong đường ray 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 
Các vấn đề liên quan