更新旧记录而不是创建新记录?

时间:2014-05-06 05:40:44

标签: ruby-on-rails ruby activerecord

我有下表:

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的事件应将updated_at设置为当前时间 - 这应该是唯一的更改。

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

4 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:1)

你可以这样做,让我们说@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)

答案 2 :(得分:1)

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

此方法将按值查找事件,或者如果此值不存在,则创建一个事件。 Touch方法将更新此记录的updated_at时间戳。

答案 3 :(得分:0)

由于您对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
相关问题