ActiveRecord 不知道时区?
ActiveRecord is not aware of timezones?
我有一个关于时区的问题
我已经完成了以下操作,当我进行以下查询时,我的 activerecord 与我的时区不匹配
def stock_by_date(date)
UserStock.where("date(created_at) = ? and user_id = ? ", date , current_user.id)
end
我在 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]
我在我的注册方法中添加了时区字段,它正确地显示了当天的时区,但是当我为当天的时区添加股票时,它显示在当前时区的前一天或第二天白天时区和当我添加我的股票时,时间戳是我查看 rails 控制台
前一天的时间
我的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
例如、
我该如何解决这个问题?
注意:如果需要更多信息,请告诉我
注意:为了简洁起见,这是我的repo
注意:我的配置根本没有显示可靠的行为,我很困惑:/我有同样的问题需要注意当天
----更新--------------------
在我的 rails 控制台中
您是否尝试通过指定范围进行查询?
因为您要查找在某个日期创建的 user_stocks
。但是请注意 created_at
是一个 datetime
对象,我猜你的 date
变量可能只是一个 date
对象。
def stock_by_date(date)
UserStock.where(created_at: date.midnight..date.end_of_day, user_id: current_user.id)
end
使用此内容创建迁移以删除 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 < 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
所以每次你创建一个,值都是正确的。这样它可能会按预期工作。
另一个选项,如果您不需要它只用于特定模型并将它们用于所有用户交互,您可以在应用程序控制器上创建一个前置过滤器以动态设置时区,例如
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 与我的时区不匹配
def stock_by_date(date)
UserStock.where("date(created_at) = ? and user_id = ? ", date , current_user.id)
end
我在 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]
我在我的注册方法中添加了时区字段,它正确地显示了当天的时区,但是当我为当天的时区添加股票时,它显示在当前时区的前一天或第二天白天时区和当我添加我的股票时,时间戳是我查看 rails 控制台
前一天的时间我的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
例如、
我该如何解决这个问题?
注意:如果需要更多信息,请告诉我
注意:为了简洁起见,这是我的repo
注意:我的配置根本没有显示可靠的行为,我很困惑:/我有同样的问题需要注意当天
----更新--------------------
在我的 rails 控制台中
您是否尝试通过指定范围进行查询?
因为您要查找在某个日期创建的 user_stocks
。但是请注意 created_at
是一个 datetime
对象,我猜你的 date
变量可能只是一个 date
对象。
def stock_by_date(date)
UserStock.where(created_at: date.midnight..date.end_of_day, user_id: current_user.id)
end
使用此内容创建迁移以删除 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 < 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
所以每次你创建一个,值都是正确的。这样它可能会按预期工作。
另一个选项,如果您不需要它只用于特定模型并将它们用于所有用户交互,您可以在应用程序控制器上创建一个前置过滤器以动态设置时区,例如
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