Ruby on rails 4 在rails迁移中使用数据更新列
我有一个事件表和会话表。事件有许多会话,这是关联。现在我只想将时区列从sessions表移动到events表。那么,如何借助迁移来实现这一点呢。如何将会话表中时区的现有记录移动到事件表中 您可以简单地使用以下迁移Ruby on rails 4 在rails迁移中使用数据更新列,ruby-on-rails-4,rails-migrations,Ruby On Rails 4,Rails Migrations,我有一个事件表和会话表。事件有许多会话,这是关联。现在我只想将时区列从sessions表移动到events表。那么,如何借助迁移来实现这一点呢。如何将会话表中时区的现有记录移动到事件表中 您可以简单地使用以下迁移 class Test < ActiveRecord::Migration def change add_column :events, :time_zone, :string Event.all.each do |e| e.update_attr
class Test < ActiveRecord::Migration
def change
add_column :events, :time_zone, :string
Event.all.each do |e|
e.update_attributes(time_zone: e.sessions.last.time_zone)
end
remove_column :sessions, :time_zone
end
end
您可以简单地使用以下迁移
class Test < ActiveRecord::Migration
def change
add_column :events, :time_zone, :string
Event.all.each do |e|
e.update_attributes(time_zone: e.sessions.last.time_zone)
end
remove_column :sessions, :time_zone
end
end
首先,您需要确保与同一事件关联的会话具有相同的时区。您可以通过以下方式执行此操作:
Session.group(:event_id).count(:time_zone)
这将返回一个哈希映射,将事件id映射到与其关联的时区数。此数字应始终为1
其次,我建议您首先添加events.time_zone并开始使用它,在新代码投入生产一段时间并被证明有效后,在单独的迁移中删除sessions.time_zone
第三,迁移以添加events.time_zone应该如下所示。为了清晰起见,我添加了一些注释:
class AddTimeZoneToEvents < ActiveRecord::Migration
class Event < ActiveRecord::Base; end
class Session < ActiveRecord::Base; end
def up
# Add a NULLable time_zone column to events. Even if the column should be
# non-NULLable, we first allow NULLs and will set the appropriate values
# in the next step.
add_column :events, :time_zone, :string
# Ensure the new column is visible.
Event.reset_column_information
# Iterate over events in batches. Use #update_columns to set the newly
# added time_zone without modifying updated_at. If you want to update
# updated_at you have at least two options:
#
# 1. Set it to the time at which the migration is run. In this case, just
# replace #update_columns with #update!
# 2. Set it to the maximum of `events.updated_at` and
# `sessions.updated_at`.
#
# Also, if your database is huge you may consider a different query to
# perform the update (it also depends on your database).
Event.find_each do |event|
session = Session.where(event_id: event.id).last
event.update_columns(time_zone: session.time_zone)
end
# If events don't always need to have time zone information then
# you can remove the line below.
change_column_null :events, :time_zone, false
end
def down
remove_column :events, :time_zone
end
end
注意,我在迁移中重新定义了模型。这样做至关重要,因为:
最初的模型可能有回调和验证,当然,您可以跳过它们,但这是一个额外的预防措施,没有任何价值。
如果您在6个月内删除模型,迁移将停止工作。
一旦确定更改按预期工作,就可以删除sessions.time\u zone。如果出现问题,您可以简单地回滚上述迁移并轻松恢复工作版本。首先,您需要确保与同一事件关联的会话具有相同的时区。您可以通过以下方式执行此操作:
Session.group(:event_id).count(:time_zone)
这将返回一个哈希映射,将事件id映射到与其关联的时区数。此数字应始终为1
其次,我建议您首先添加events.time_zone并开始使用它,在新代码投入生产一段时间并被证明有效后,在单独的迁移中删除sessions.time_zone
第三,迁移以添加events.time_zone应该如下所示。为了清晰起见,我添加了一些注释:
class AddTimeZoneToEvents < ActiveRecord::Migration
class Event < ActiveRecord::Base; end
class Session < ActiveRecord::Base; end
def up
# Add a NULLable time_zone column to events. Even if the column should be
# non-NULLable, we first allow NULLs and will set the appropriate values
# in the next step.
add_column :events, :time_zone, :string
# Ensure the new column is visible.
Event.reset_column_information
# Iterate over events in batches. Use #update_columns to set the newly
# added time_zone without modifying updated_at. If you want to update
# updated_at you have at least two options:
#
# 1. Set it to the time at which the migration is run. In this case, just
# replace #update_columns with #update!
# 2. Set it to the maximum of `events.updated_at` and
# `sessions.updated_at`.
#
# Also, if your database is huge you may consider a different query to
# perform the update (it also depends on your database).
Event.find_each do |event|
session = Session.where(event_id: event.id).last
event.update_columns(time_zone: session.time_zone)
end
# If events don't always need to have time zone information then
# you can remove the line below.
change_column_null :events, :time_zone, false
end
def down
remove_column :events, :time_zone
end
end
注意,我在迁移中重新定义了模型。这样做至关重要,因为:
最初的模型可能有回调和验证,当然,您可以跳过它们,但这是一个额外的预防措施,没有任何价值。
如果您在6个月内删除模型,迁移将停止工作。
一旦确定更改按预期工作,就可以删除sessions.time\u zone。如果出现问题,您可以简单地回滚上述迁移并轻松恢复工作版本。在迁移中不应使用模型。它们可以触发回调、验证等。此外,它们还可以随时间而变化,即如果您在6个月内删除模型,迁移将停止工作。您不应该在迁移中使用模型。它们可以触发回调、验证等。此外,它们还可以随时间而变化,即如果您在6个月内删除模型,迁移将停止工作。这是有效的。如果出现故障,是否应该有任何方法来恢复会话表中的时区?请注意,我没有删除sessions.time\u zone。请参阅最后一段-我建议您首先迁移到新列,让您的代码使用它,一旦确定它可以工作,就删除旧列。数据库存储很便宜,所以不用着急。。我错过了那部分。。这有助于。。创建第三个表来存储关联(如events\u sessions表)是否有意义?这样的表用于多对多关系中。如果我正确理解您的情况,会话的时区应该来自相应的事件。在这种情况下,创建这样的表是没有意义的。您可以使用def time_zone将Sessiontime_zone委托给Eventtime_zone;事件。时区;结束或委托你做这件事。如果出现故障,是否应该有任何方法来恢复会话表中的时区?请注意,我没有删除sessions.time\u zone。请参阅最后一段-我建议您首先迁移到新列,让您的代码使用它,一旦确定它可以工作,就删除旧列。数据库存储很便宜,所以不用着急。。我错过了那部分。。这有助于。。创建第三个表来存储关联(如events\u sessions表)是否有意义?这样的表用于多对多关系中。如果我正确理解您的情况,会话的时区应该来自相应的事件。在这种情况下,创建这样的表是没有意义的。您可以使用def time_zone将Sessiontime_zone委托给Eventtime_zone;事件。时区;结束或委托给。