【问题标题】:Update old record instead of creating a new one?更新旧记录而不是创建新记录?
【发布时间】:2014-05-06 05:40:43
【问题描述】:

我有下表:

event_id  value   created_at        updated_at
1         15.2    2014/01/01 00:00  2014/01/01 00:00
2         15.5    2014/01/01 00:10  2014/01/01 00:10
3         15.9    2014/01/01 00:20  2014/01/01 00:20

但是,如果一个新事件与前一个事件具有相同的值(如在最新的时间),那么前一个事件应该将“updated_at”设置为当前时间,并且不应创建新事件。

在上面的示例中,如果我执行 Event.new(:value => 15.9),则 ID 为 3 的 Event 应将其 updated_at 设置为当前时间 - 这应该是唯一的更改。

关于如何完成此任务的任何建议?我曾尝试摆弄 Active Record 回调,但在中止创建(使用回滚)时失败。当然可以使用特殊的“构造函数”方法来解决,但我想避免这种情况。

【问题讨论】:

  • Google for find_or_create_by

标签: ruby-on-rails ruby activerecord


【解决方案1】:
Event.where(value: params[:value]).first_or_create.touch

或在 event.rb 中

before_save :update_if_existing

private 
def update_if_existing
  if event = Event.find_by(value: value)
    event.touch # updates the updated_at timestamp if the existing event
    false       # prevents the current event from being inserted into the db
  end
end

【讨论】:

  • 谢谢,我会接受这个答案,因为它将逻辑放在模型对象而不是控制器中。
  • 谢谢。请记住,它仍然返回新的未保存的Event,而不是已经存在的Event。您可能需要在控制器中处理它。
【解决方案2】:
Event.find_or_create_by_value(params[:value]).touch

此方法将按值查找事件,如果具有此值的事件不存在,则创建一个。触摸方法会更新这条记录的updated_at时间戳。

【讨论】:

    【解决方案3】:

    您可以这样做,假设@event 是对象,在保存之前您要检查值

    unless @event.value == Event.last.value     
      @event.save
    else
      Event.last.update_attributes(:updated_at => DateTime.now)
    end
    

    或者您可以使用三元运算符在一行中完成此操作

    (@event.value == Event.last.value) ? (Event.last.update_attributes(:updated_at => DateTime.now)) : (@event.save)
    

    【讨论】:

      【解决方案4】:

      由于您对 Event 的定义是任何两个事件都不应具有相同的 value - 您应该在该字段上添加一个唯一索引,这也将使任何此类操作更快。

      实际上,由于您的事件不是由其id 定义,而是由其value 定义,请考虑将其primary key 更改为value

      create_table(:event, :primary_key => 'value') do |t|
        t.column :userID, :decimal, :null => false
        ...
      end
      
      class Event
        set_primary_key :value
        ...
      end
      

      现在你可以简单地做:

      Event.find_or_create_by_value(params[:value]).touch
      

      【讨论】:

      • 表中的两个事件可以具有相同的值,但不按顺序排列。 IE。 15.2、15.5、15.2 没问题。但不是 15.2、15.2。
      • @Ciryon - 抱歉,您的问题并不明显。在那种情况下,我认为只有 RSB 做对了……其余的答案在全球范围内寻找。
      猜你喜欢
      • 1970-01-01
      • 2020-07-08
      • 2023-01-12
      • 1970-01-01
      • 1970-01-01
      • 2012-07-25
      • 2021-03-30
      • 1970-01-01
      • 2011-12-10
      相关资源
      最近更新 更多