Reputation: 2777
I have the following table:
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
However, if a new Event has same value as the previous (as in newest in time) Event, then the previous Event should have "updated_at" set to current time and no new Event should be created.
In the example above, if I do Event.new(:value => 15.9), then Event with id 3 should have its updated_at set to current time - and that should be the only change.
Any suggestions on how to accomplish this? I have tried fiddling with Active Record callbacks, but fail when aborting creation (using rollback). It is of course possible to solve using a special "constructor" method, but I'd like to avoid that.
Upvotes: 1
Views: 362
Reputation: 37409
Since your definition of Event is that no two events should have the same value
- you should add a unique index on that field, which will also make any such operations much quicker.
Actually, since your event is not defined by its id
but by its value
, consider changing its primary key to value
:
create_table(:event, :primary_key => 'value') do |t|
t.column :userID, :decimal, :null => false
...
end
class Event
set_primary_key :value
...
end
Now you can simply do:
Event.find_or_create_by_value(params[:value]).touch
Upvotes: 0
Reputation: 17834
You can do this way, let's say @event
is the object and before saving you want to check the value
unless @event.value == Event.last.value
@event.save
else
Event.last.update_attributes(:updated_at => DateTime.now)
end
or you can do this in a single line using ternary operator
(@event.value == Event.last.value) ? (Event.last.update_attributes(:updated_at => DateTime.now)) : (@event.save)
Upvotes: 1
Reputation: 11967
Event.find_or_create_by_value(params[:value]).touch
This method will find event by value or create one if event with this value doesn't exist. Touch method will update updated_at
timestamp for this record.
Upvotes: 1
Reputation: 106872
Event.where(value: params[:value]).first_or_create.touch
or in 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
Upvotes: 4