"Rails" Rankinis puslapiavimas (Pagination)

Posted by Mindaugas Kurlavičius 04/09/2007 at 22h32

Beveik kievienoje tinklo aplikacijoje yra reikalingas įrašų puslapiavimas. Kas tai yra, labai lengva suprasti apsilankius Google puslapyje. Ten visi paieškos rezultatai suskirstyti po 10 ir pateikiami atskiruose puslapiuose, į kuriuos nuorodos yra tvarkingai sudėliotos rezultatų apačioje.

Programiniame lygmenyje puslapiavimo algoritmas nėra labai sudėtingas, aplikacijai reikalingi tik du parametrai - įrašų skaičius vienam puslapiui (:limit), ir norimas puslapis (:page). Su šiais parametrais galime apskaičiuoti trečią parametrą - (:offset) pagal formulę offset = limit * (page - 1) ir formuoti efektyvias SQL užklausas kiekvienos užklausos metu iš DB pasiimdami tik reikalingą kiekį užrašų einamajam puslapiui. Paprasta, tačiau puslapiavimas vis dėl to yra nemenkas galvos skausmas programuotojams, o "Rails" bendruomenėje ima vyrauti nuomonė, jog pačio paprasčiausio "Rails" puslapiavimo geriau išvis nenaudoti : Things you shoudnt be doing in Rails.

Dokumentacijoje nurodytas metodas:

@person_pages, @people = paginate(
  :people, 
  :order => 'last_name, first_name'
)
atrodo labai patraukliai, tačiau praktikoje iš jo gali būti per mažai naudos. Jo trūkumas yra tas, kad negalima perduoti einamojo puslapio parametro, t.y. jis naudoja params[:page], taigi tokio modelio puslapyje, kur einamasis puslapis visada turi būti fone, nesvarbu, kokį kitokį veiksmą atlikome, prie kiekvienos nuorodos turime "prikabinti" params[:page]. Be, to tradicinis pagalbinis metodas "pagination_links" retai tinka praktiškai.

Patogus būdas (padedantis išvengti galvos skausmo) realizuoti puslapiavimą , tai pasidaryti rankomis pagalbinį metodą (kontrolerio arba bibliotekos) naudojantį žemesnio lygio puslapiavimo metodus.

def my_pagination(user, limit, page)
  @total = Record.count(:conditions => {:user_id => user.id})
  @records = Record.find(
    :all, 
    :conditions =>  {:user_id => user.id },
    :order      =>  'created_at DESC',
    :limit      =>  limit,
    :offset     =>  limit.to_i * (page.to_i - 1)
  )
  @record_pages = Paginator.new(self, @total, limit, page)
end

Tokį metodą naudojant kontrolerio veiksmuose (action), gaunami trys kintamieji iš kurių vėliau nesunku pasidaryti nuorodas į puslapius.

Taip pat, patogu yra params[:page] parametrą "prikabinti" tik prie nuorodų į įrašų puslapius, ir gavus aplikacijoje išsaugoti arba sesijos kintamajame arba kokiuose nors vartotojo nustatymuose, o užklausose, kuriose params[:page] nėra, naudoti išsaugotą parametrą.

no comments | no trackbacks

Comments

Trackbacks

Use the following link to trackback from your own site:
http://www.rubyonrails.lt/trackbacks?article_id=20

(leave url/email »)

reCaptcha

   Comment Markup Help Preview comment