ActiveRecord 不知道时区? [英] ActiveRecord is not aware of timezones?

查看:56
本文介绍了ActiveRecord 不知道时区?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于时区的问题

我已经完成了以下操作,当我执行以下查询时,我的 activerecord 仍然与我的时区不匹配

def stock_by_date(date)UserStock.where("date(created_at) = ? and user_id = ? ", date , current_user.id)结尾

我在 application.rb

中做了以下操作

config.active_record.default_timezone = :utcconfig.active_record.time_zone_aware_attributes = trueconfig.beginning_of_week = :sundayconfig.active_record.time_zone_aware_types = [:datetime,:time]

我在注册方法中添加了时区字段,它正确显示了当前时区,但是当我为当前时区添加股票时,它显示在当前白天时区的前一天或后一天当我添加我的股票时,时间戳是我查看 rails 控制台的前一天

我的schema.rb

ActiveRecord::Schema.define(version: 2018_11_28_183416) 做create_table "friendships", force: :cascade do |t|t.integer "user_id"t.integer "friend_id"t.datetime "created_at", null: falset.datetime "updated_at", null: falset.index ["friend_id"],名称:"index_friendships_on_friend_id"t.index ["user_id"],名称:"index_friendships_on_user_id"结尾create_table "notes", force: :cascade do |t|t.string "内容"t.datetime "created_at", null: falset.datetime "updated_at", null: falset.integer "user_id"t.index ["user_id"],名称:"index_notes_on_user_id"结尾create_table "stocks", force: :cascade do |t|t.string 股票代码"t.string "名称"t.decimal "last_price"t.datetime "created_at", null: falset.datetime "updated_at", null: false结尾create_table "user_stocks", force: :cascade do |t|t.integer "user_id"t.integer "stock_id"t.datetime "created_at", null: falset.datetime "updated_at", null: falset.index ["stock_id"],名称:"index_user_stocks_on_stock_id"t.index ["user_id"],名称:"index_user_stocks_on_user_id"结尾create_table "users", force: :cascade do |t|t.string "email", 默认: "", null: falset.string "encrypted_pa​​ssword", 默认值: "", null: falset.string "reset_password_token"t.datetime "reset_password_sent_at"t.datetime "remember_created_at"t.datetime "created_at", null: falset.datetime "updated_at", null: falset.string "first_name"t.string "last_name"t.string "time_zone",默认值:"UTC"t.index ["email"], 名称: "index_users_on_email", 唯一: truet.index ["reset_password_token"],名称:"index_users_on_reset_password_token",唯一的:true结尾结尾

例如

我该如何解决这个问题?

注意:如果需要更多信息,请告诉我

注意:为了简洁,这是我的

解决方案

使用此内容创建迁移以删除 created_at 的默认值,因此它不会在数据库级别默认填充.

change_column_default(:user_stocks, :created_at, nil)

之后,当您创建一个新的 UserStock 时,您需要指定 created_at 值,并且您可以在那里指定 created_at 与用户的日期,注意时区.

UserStock.create(created_at: Time.now.in_time_zone(user.time_zone).to_time...)

或者您可以将它添加到模型的回调中,这样每次创建 UserStock 时它都会自动更改值

class UserStock 

所以每次创建一个时,值都是正确的.它可能会按预期工作.

另一个选项,如果您不需要它只用于特定模型并将它们用于所有用户交互,您可以在应用程序控制器上创建一个 before 过滤器以动态设置时区,例如

class ApplicationController <动作控制器::基础before_filter :set_time_zonedef set_time_zone(&block)time_zone = current_user.try(:time_zone) ||'世界标准时间'Time.use_zone(time_zone, &block)结尾结尾

I have one question regarding to time zone

I have done the following yet, my activerecord is not still matching with my timezone when I do following query

def stock_by_date(date)
   UserStock.where("date(created_at) = ? and user_id = ? ", date , current_user.id)
end

I did the following in side my application.rb

config.active_record.default_timezone = :utc
config.active_record.time_zone_aware_attributes = true
config.beginning_of_week = :sunday
config.active_record.time_zone_aware_types = [:datetime, :time]

I added timezone field to my sign up method, and it shows the current day of timezone correctly, yet when I added a stock for the current day timezone, it shows up in either the previous day or next day of current daytime zone and when I added my stock, the timestamp is for a day before when I look at the rails console

My schema.rb

ActiveRecord::Schema.define(version: 2018_11_28_183416) do

  create_table "friendships", force: :cascade do |t|
    t.integer "user_id"
    t.integer "friend_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["friend_id"], name: "index_friendships_on_friend_id"
    t.index ["user_id"], name: "index_friendships_on_user_id"
  end

  create_table "notes", force: :cascade do |t|
    t.string "content"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "user_id"
    t.index ["user_id"], name: "index_notes_on_user_id"
  end

  create_table "stocks", force: :cascade do |t|
    t.string "ticker"
    t.string "name"
    t.decimal "last_price"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "user_stocks", force: :cascade do |t|
    t.integer "user_id"
    t.integer "stock_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["stock_id"], name: "index_user_stocks_on_stock_id"
    t.index ["user_id"], name: "index_user_stocks_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "first_name"
    t.string "last_name"
    t.string "time_zone", default: "UTC"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

end

for example,

How can I fix this issue?

Note: If more info is needed, please let me know

Note: for the matter of being concise this is my repo

Note: my configuration does not show a reliable behavior at all and I am very confused :/ and I have the same issue for note of a current day

----update-------------------

In my rails console

解决方案

create a migration with this content to remove the default value to created_at, so it's not filled by default on database level.

change_column_default(:user_stocks, :created_at, nil)

after that, when you create a new UserStock, you need to specify the created_at value, and there you can specify the created_at with the date of the user, taking care of the timezone.

UserStock.create(created_at: Time.now.in_time_zone(user.time_zone).to_time...)

or you can just maybe add it to a callback on the model so it's automatic everytime you create a UserStock, it change the value

class UserStock < ActiveRecord::Base
  before_create :set_created_at

  private
    def set_created_at
      self.created_at = time.now.in_time_zone(self.user.time_zone).to_time
    end
end

so everytime you create one, the value is correct. with that it may work as expected.

Another option if you don't need it just for that specific model and use them for all the user interaction, you can create a before filter on the application controller to set the time zone dinamically, something like

class ApplicationController < ActionController::Base
  before_filter :set_time_zone

  def set_time_zone(&block)
    time_zone = current_user.try(:time_zone) || 'UTC'
    Time.use_zone(time_zone, &block)
  end
end

这篇关于ActiveRecord 不知道时区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆