Edit:
Is it possible to create a unique auto increment field that will be incremented on creates and updates in SQL using Rails (similar to an id field but incremented and re-assigned after an update)? For example:
Create Record A (Value: 1)
Create Record B (Value: 2) Update Record A (Value: 3) Update Record B (Value: 4)
I'm trying to setup pull synchronization and need a way to grab all records that have been created or updated since a previous synchronization.
I initially used the 'created_at' and 'updated_at' fields, but found them to be difficult to work with and somewhat inaccurate for partial synchronizations.
Edit:
I'm using Postgresql and Sqlite as my databases, so hopefully a solution exists that will work for both systems.
Edit:
To clarify, I want to pass a single integer to my server from the client (the largest 'sync' integer) and get back all the records created or updated after that record was开发者_高级运维 created or updated.
Ended up adding a sequence
integer field to my model and setup the following migration:
class CreateSequence < ActiveRecord::Migration
def self.up
begin
execute "CREATE SEQUENCE sequence"
rescue
end
end
def self.down
begin
execute "DROP SEQUENCE sequence"
rescue
end
end
end
Then, in my model I added:
before_save do
self.sequence = self.class.sequence
end
def self.sequence
s ||= self.connection.select_value("SELECT nextval('sequence') ") rescue nil
s ||= self.connection.select_value("SELECT strftime('%s','now')") rescue nil
return
end
Note: For Sqlite sequences are not supported so instead a selection of an 'epoch' form the database is required. However, this has the negative side effect of causing the sequence to be non-unique for rapid creation. However, in my case this was not an issue.
You could use a before_save
callback, like so:
class MyModel < ActiveRecord::Base
before_save :increment
...
protected
def increment
self.revision ||= 1
self.revision += 1
end
end
You could make this more reusable by defining and using a Callback Class.
Another option it to use a Gem/plugin that does automatic versioning (and thus maintains a version
field).
Whoops, didn't read too carefully.
If you want to grab the records that have been modified since the last sync you could create a boolean field for determining if the current record was synced. Set it to false by default and set it to false on any edit. That should allow you to pull only the items you need.
There is an id attribute that is provided by default and it auto increments. By default it is an integer, however if you were looking for a guid then let me know and I can point you to some good resources.
As far as pulling records since the last sync you could just grab the last id when you run the sync and use it as a starting value when you sync again.
So... the serial number is not associated with a row so much as a table, right?
class SerialNumber < AR::Base
has_many :thingies
# just has an integer serial number field
end
class Thingie < AR::Base
belongs_to :serial_number # probably want to include this in default scope
before_create :bump_serial
before_save : bump_serial
private
def bump_serial
self.serial_number ||= 0
self.serial_number += 1
end
end
This would appear to handle the cases of create, new/save, and update. But not destroy.
Try using the act_as_versioned gem. It sets a version field for each record that you could use for synchronization. And I think that this would be a better way to synchronize across clients since you can compare the version on the server and client and synchronize those that are higher on the server.
The docs are here. And the rubygem page is here.
精彩评论