Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 4 在rails迁移中使用数据更新列_Ruby On Rails 4_Rails Migrations - Fatal编程技术网

Ruby on rails 4 在rails迁移中使用数据更新列

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

我有一个事件表和会话表。事件有许多会话,这是关联。现在我只想将时区列从sessions表移动到events表。那么,如何借助迁移来实现这一点呢。如何将会话表中时区的现有记录移动到事件表中

您可以简单地使用以下迁移

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;事件。时区;结束或委托给。