开发者

Rails Unique Order Field For Create and Update Operations

开发者 https://www.devze.com 2023-03-09 16:39 出处:网络
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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消