0

I have a Sinatra app using datamapper for its database handling. The app works by displaying a separate page for each ID in a table.

The model has an id field, which is a serial value and it's set up as the key.

Currently, I browse between records using links which add or subtract 1 from the current ID. This is less than ideal, because it breaks once I delete a record in the middle.

Is there a .next method or something in Datamapper that I can use to make this work?

Nekkoru
  • 1,145
  • 2
  • 12
  • 18

2 Answers2

2

You can search the next and previous ids and use them to build your links (instead of using your current ID + or - 1).

# Record/123 : display a record
get '/record/:id' do

  # Get record belonging to id
  @record = Record.first({id: params[:id]})

  # Get id for next record
  next = Record.first({:fields => [:id],
                       :order => :id.asc,
                       :id.gt => @record.id})
  # (or the first record)
  next = Record.first({:fields => [:id],
                       :order => :id.asc}) unless next
  @next_id = next[:id]

  # Get id for previous record
  prev = Record.last({:fields => [:id],
                      :order => :id.asc,
                      :id.lt => @record.id})
  # (or the last record)
  prev = Record.last({:fields => [:id],
                      :order => :id.asc}) unless prev
  @prev_id = prev[:id]

  # Display the record
  erb :record

end

Then you just have to use @next_id and @prev_id in your view to reach the right url.

The "(or the first record)" part is used to move to the first record when you are at the end (ie there is no record after the current one).

Edit :

  # Get id for next record
  next = Record.first({:fields => [:id],
                       :order => :id.asc,
                       :id.gt => @record.id})

We need to find the next ID after the current ID in the table. With SQL, it's :

   SELECT Id                  # :fields => [:id]
   FROM   Records 
   WHERE  Id > Current_Id     # :id.gt => @record.id
   ORDER BY Id ASC            # :order => :id.asc

Without ":fields => [:id]", we will have a "SELECT *" when we only need the ID.

Michel
  • 706
  • 3
  • 6
  • This does look like it works, but I don't exactly get it. Could you help me understand what goes on here? next = Record.first({:fields => [:id], :order => :id.asc, :id.gt => @record.id}) – Nekkoru Mar 14 '13 at 10:18
1
current = Model.get id
next = Model.all(:id.gt => current.id, :order => [:id.asc]).first

It grabs the first object with an id larger than the current object.

AlexQueue
  • 6,353
  • 5
  • 35
  • 44