Anyone who’s used Ruby on Rails has likely needed to implement pagination, and for that you probably used WillPaginate. Although it’s been possible to use WillPaginate with Sequel for some time now, we’ve only just seen the first Roda GEM released. After some experiementation, it turns out adding pagination to our Roda app is actually pretty easy.
We’ll be building on top of my Roda Blog tutorial so if you don’t already have an application to try this with then you should take a look at that first.
Here’s the versions and GEMs I’ll be using for this tutorial;
Our first task is too add
roda-will_paginate to our
Gemfile – don’t forget to
bundle install once you’ve done that.
# ./Gemfile gem "roda-will_paginate", ">= 0.0.4"
The plugin only handles generating the HTML links on your view pages, so we need to make sure our blogs
Post collection includes the required WillPaginate methods. As the plugin README states, “That would mean adding
total_pages as methods of your collection and including
WillPaginate::CollectionMethods in your collections as well.”
That’s quite a bit of work, but lucky for us we’re using Sequel, and WillPaginate supports that out-of-the-box.
In my last article we built a simple Roda website, which let us deliver some rather static pages. We’ll build on that work by implementing some basic blogging features such as User accounts and Posts.
Note: as this article was posted in April 2015 I can not guarantee it will still work with the latest versions Roda.
We’ll be using a PostgreSQL database, the defacto DB of many Rubyist, which we’ll interact with using Sequel, an excellent ORM by Jeremy Evans, who is also the developer behind Roda.
Please make sure to install PostgreSQL before continuing. Once that’s done we need to add the appropriate RubyGems to our Gemfile;
# ./Gemfile gem "pg", "~> 0.18.1" gem "sequel", "~> 4.21.0"
bundle install we need to connect Sequel to the database. In a real world application we’d want to keep our
myapp.rb uncluttered by placing the configuration in a separate
database.yml file, and ORM initialization in
database.rb, but I’ll simplify that for this tutorial by including everything right in the main app file.
# ./myapp.rb require "roda" require "sequel" database = "myapp_development" user = ENV["PGUSER"] password = ENV["PGPASSWORD"] DB = Sequel.connect(adapter: "postgres", database: database, host: "127.0.0.1", user: user, password: password) class Myapp < Roda # ... end
It can be useful to use environment variables for things like usernames and passwords, which is what I’ve done here, but if you’d like, just replace the
ENV directly with your database user/password credentials. If your
host setting is different then make sure to change that too.
I’m currently experimenting with building a web application using Sinatra and the Sequel ORM, and as is often required in database driven applications, I need to pull a bunch of records yet exclude those that don’t have any associated records in a
one_to_many relationship (
has_many in Rails parlance).
Imagine we are building a blog platform where we can have Post’s that get assigned to a Category (
many_to_one). When listing our available categories we don’t want to be showing any that haven’t any posts assigned. I wasn’t able to gleam anything specific about doing this from the Sequel documentation, so after a prolonged hair-pulling session I came to the following solution.
First, here’s the basic outline of our models;
class Post < Sequel::Model many_to_one :category end class Category < Sequel::Model one_to_many :posts dataset_module do def with_posts where(id: Post.select(:category_id)) end end end
As you can see, we are using a
dataset_module to set the scope for our query, allowing us to call
.with_posts wherever we need a listing of categories. The
where(id: Post.select(:category_id)) tries to match any Post that has our
category.id. Using our new scope we can now set our controller like so;
get "/categories" do @categories = Category.with_posts.order(:name) erb :categories end
In Rails we have the option to set a counter cache on the Category model;
posts_count, which let’s us filter by that. Sequel has the
sequel_postgresql_triggers plugin, which let’s you do the same (using
pgt_counter_cache) if you are using PostgreSQL, although I haven’t looked into that just yet.
Hi, my name is Michael and this is my personal blog. Here I’ll be posting various coding thoughts and experiments; everything from writing blogs in Ruby, to Go tools and Z80 Assembly. This site is powered by Thunderaxe, a blogging platform I built using the Roda Ruby framework.