Rails class caching / reloading and Engines

Plugins, Ruby on Rails 1 Comment »

I’ve been playing around with Engines a bit at work, and I ran into an issue where I had to restart the server over and over due to class caching issues.

To make a long story short, I was able to force Rails to reload the particular engine I was using by adding the following to the engine’s init.rb:


%w(controllers helpers models views).each {|path| Dependencies.load_once_paths.delete File.join(File.dirname(__FILE__), 'app', path) }
Dependencies.load_once_paths.delete File.join(File.dirname(__FILE__), 'lib')

This worked with Rails 2.1 and an unknown version of the Engines plugin.

MerbDay Atlanta

Ruby on Rails 9 Comments »
Merb Day

I attended MerbDay in Atlanta this weekend, and while enlightening, it was ultimately a blah experience. In all honesty, I feel like I paid $60 to attend a Ruby meetup and get a breakfast and lunch.

The highlight to me was a quick introduction to HAML / SASS. While not strictly Merb related, both look very cool. Still, when I subtract out the cool factor, I’m not sure there’s a big incentive to use them over straight up HTML and CSS. Nonethelesss, very interesting.

So, all in all, I’m glad I learned a little about Merb, but I don’t feel like I’ve gotten any more from this than I could by perusing a HOWTO and following along at home for an hour or so. I guess that’s why this was $60, instead of being a $$$ multi-day training course.

@merbday twitpay -$60 for making me pay for a ruby meetup

Just a little joke. One of the main presenters of MerbDay helped create twitpay. Seriously, I’m glad I came.

Open mouth, insert foot

I’ve been called out in the comments for judging a little too early, and it turns out they’re right. The day picked up near the end, culminating with a great keynote by Yehuda Katz. Plus, $60 for a day full of good info is still pretty cheap, even it’s presented like an extended Ruby meetup. Throw in breakfast, lunch, and free beers afterward (paid for by Rails Machine) and it turns out to be a pretty good day. So, I end up the one with egg on my face for being snarky and prematurely bitching.

Constructive Criticism

In order to be a little less whiny and lessen my troll karma, I’ll offer the following constructive criticism:

I would say to have fewer presentations and perhaps some breakout sessions with small groups writing an app. Make it a hackfest rather than a list of presentations. Teams of 3 and a script to follow, with gurus prowling the room giving help when asked. Maybe that would suck, but I feel like I’d learn more.

Also, I really don’t think the “write code while you’re following along” approach really works. It’s just too hard to stay with the presenter, and it’s too easy to run into small problems (don’t have this-or-that gem installed, small typo, etc.). Plus, if you try to do a pull and catch up with the real repo, you’ll probably encounter conflicts and that will suck.

So, hopefully this explains my complaints a little better. I’ll try to be more constructive and less snarky in the future.

Facebooker tunnel and Phusion Passenger

Ruby on Rails 1 Comment »

If you’re using the Facebooker SSH tunnels along with Phusion Passenger, you may run into an issue where you have multiple Rails apps running on your machine at different subdomains. Unfortunately, when facebook makes a request to your tunnel, it’s passed through on port 80 to your local machine and Apache chooses the first defined virtual host to serve the request, which may or may not be the one you want.

An easy solution is to use a ServerAlias directive in your vhost file that matches up with your tunnel domain.


<VirtualHost *:80>
ServerName my.local.rails.app.localhost
ServerAlias my.tunnel.domain
DocumentRoot /path/to/rails/app/public
</VirtualHost>

This works because the tunnel will pass the request through to your machine without changing any of the request headers. So, they come through with the Host header set to the tunnel domain, and Apache will match it to your server alias.

Rails, Textile, and javascript WYSIWYG roundup

Plugins, Projects, Ruby on Rails 4 Comments »

If you allow rich text from your users in a Rails app, then you’re probably familiar with Textile. Either that or you’ve chosen the dark side, aka. Markdown. If that’s the case, I hate everything you stand for and I’ll bet you put your curly braces on the wrong line!

Assuming you’re one of The Chosen who has selected Textile as your input syntax of choice, you’ve probably got plenty of users who are turned off by the syntax. It may be easy for your average web developer to pick up yet another new syntax, but there are lots of people on the web who have never clicked the edit tab on Wikipedia, or think that links are specified with [URL=http://bbcode.com].

For these people, some sort of help is necessary. Quick tip sidebars, tutorials, and help pages only go so far. To make it truly useful you’ll probably have to dip into your Javascript bag of tricks. Luckily for you, a few others have already blazed that trail and created a handful of Textile utilities.


Textile Editor Helper (TEH)

NOTE: We’ve forked the Textile Editor Helper plugin to have more features and to conform to Rails 2.1 conventions. Our fork is available on github here:
http://github.com/felttippin/textile-editor-helper/tree/master

Textile Editor

The Textile Editor Helper is a very simple toolbar that sits at the top of your textareas, much like the Wikipedia toolbar. It provides many of the most basic Textile options, like bold and italics, plus some text alignment. Unfortunately, it doesn’t include linking and image includes, which are really easy to do with Textile.

Supposedly, you can add your own buttons, but I haven’t confirmed this. Plus, I think the whole plugin is based around the idea of prefixes/suffixes for text (like * for strong, or _ for em), so anything that requires more than that might not be possible. So, TEH is a good solution if all you need is some basic formatting help.

Live Textile Preview


The Live Textile Preview (aka SuperTextile) is simply a Javascript implementation of the Textile parser. So, you can convert Textile to HTML on the client side. This allows users to experiment with the syntax and quickly see what the changes will look like.

Unfortunately, from my cursory testing, it only implements most of the Textile syntax. Basic text changes, images, and links are covered. However, advanced text alignment and CSS styling elements seem to be beyond its capabilities. So, it’s not perfect. Still, if you only need the basics, SuperTextile can make life bearable for your users.

Sanskrit WYSIWYG editor

Sanskrit

Sanskrit is a true WYSIWYG editor, and the only one I’ve seen for Textile. However, it only does the absolute basics, so I can’t recommend it. Plus, I don’t think it’s a great idea to hide the raw Textile from your users. I’m a fan of the Wikipedia / Mediawiki way of things, where you provide some editing help, but your users are always looking at the raw text. Eventually, they’ll get the hang of things and won’t need the crutch of the editor buttons anymore.

markItUp!

markItUp! could be the most promising of all the solutions. A general purpose syntax parser written on top of jQuery, markItUp! can translate any syntax into HTML, provided you write the correct parser. Further, someone has already gone through the trouble and created a Textile parser!

I haven’t installed or tested markItUp!, but I was very impressed after playing around with the Textile demo. It seemed capable of most of the Textile syntax (including links and images), and even included a handy-dandy preview feature (you must render on the server side and return the HTML, I believe). So, it includes the best of all worlds: users work on raw Textile, but can get a live preview at the click of a button.

Update I finally got a chance to play with markItUp and it is hands down the best editor out of the bunch. Unless you need a true wysiwyg (in which case Sanskrit is the only one, AFAIK), then skip all the others and go straight to markItUp.

More?

Well, that’s all the Textile help I’ve found so far. Each one has its plusses and minuses, but any of them is probably better than a bare textarea with little or no help.

If I’ve left anything out, please let me know and I’ll add it to the list. With a little help, we can put together a comprehensive list of all the Textile tools available for Rails programmers.

Boosh! My first Rails core contribution gets accepted!

Ruby on Rails 1 Comment »

I submitted my first Rails core contribution a while back, and I just happened to check in and see that it was accepted!

Amazon EC2 first thoughts

Obsidian Portal, Ruby on Rails 1 Comment »

I’ve had my first brush with EC2 today, and I’m thoroughly confused and exhausted. It definitely has a much steeper learning curve than the other Web Services. However, since you’re dealing with booting and configuring fully functional virtual machines, I guess that’s to be expected.

Still, I managed to spawn an instance, set all the necessary permissions, and then connect to it via ssh. Not exactly something to brag about, but it is a milestone. I consider it $0.20 well spent. :) (I had to terminate and re-run the instance because I didn’t store the key-pair RSA key the first time.)

The goal

For Obsidian Portal, the map processing and tiling is very CPU and RAM intensive. If run on our Slicehost VPS, it totally bogs down the whole system, making the main website completely unresponsive.

So, we’ve offloaded the processing to a machine in Ryan’s attic. Although it’s worked so far, it’s not exactly a professional solution. Plus, Ryan’s getting ready to move and his machine will be off for at least a week. That means we need a new place to run our stuff. Since I’ve been meaning to dive into EC2 for a while now, this seems like the perfect opportunity to put in place a permanent and professional solution.

The plan

Whenever we need to tile a map, I plan to spin up an EC2 instance and run the tiler. I’ll keep the instance up for the rest of the hour, in case more maps come in. When the hour runs out, if there are no more maps to process, then we’ll spin down the instance. Computing power on demand…nice!

grempe-amazon-ec2

If you’re a Ruby hacker, skip the EC2 toolset altogether. Just go get the grempe-amazon-ec2 gem and run all your EC2 requests through an irb shell. This allows for opening up the EC2 developer reference and learning the API commands straight from the docs, rather than having to learn the EC2 toolset. You’re probably going to have to spawn/terminate instances dynamically at some point, so you may as well just learn how right from the start.

Besides, the EC2 toolset route involves setting up a JVM, setting JAVA_HOME, and all that Java mumbo-jumbo that always takes way longer than it should. Save yourself a headache and go straight to the source.

ec2onrails

I’m not looking to run a full Rails server (yet), but we do want to run some rake tasks. Rather than hand build an image, I’ve decided to start with the ec2onrails image and see if that gets me most of the way there.

The main downside is that this image will need to install RMagick, ImageMagick, and possibly other gems and packages each time it spins up. ec2onrails has built-in support for this, but it means that the map processing can’t start for several minutes after the image boots up, meaning our users have to wait to see their maps. For now, it should be acceptable, but it’s something to improve on.

Next Steps

I’ve had enough for today, but there’s still a ways to go. I need to complete the following:

  1. Setup the cron job on our VPS to spawn the EC2 instance whenever a map needs processing (and there’s not already an instance running)
  2. Setup the script (rake task?) for the EC2 image that will do the processing. It may as well just run forever. Maybe it can be responsible for terminating the image? Hmm…that sounds dangerous. If it should crash out, then the instance will keep running and billing us!
  3. Surely there’s more…

Oh, and one other next step: I’d better go terminate the instance I left running! ;)

Beware of ssl_requirement

Plugins, Ruby on Rails 6 Comments »

If you’re starting out with SSL and Rails, you’ll probably stumble upon ssl_requirement very quickly. It promises to make routing easy by automatically redirecting to SSL when required (hence the name…). However, in most cases, that’s not enough, and relying solely on ssl_requirement will leave you unprotected.

ssl_requirement really only protects you in one direction, when the client requests data that should be encrypted when sent from the server. However, it does not really do much for you in the oh-so-important case of transmitting sensitive data from the client to the server.

Now, if your entire site is SSL (ie. Apache redirects all incoming requests to HTTPS), then it’s not really a problem. Your form_tag or form_for calls will pick up on the fact that they are being served from an SSL protected page, and they themselves will submit to HTTPS. However, in the case of a non-encrypted page that has a form that should be encrypted (ie. login form on the homepage), the form will default to submitting to regular HTTP, since it defaults to use the protocol of the current page. This is where ssl_requirement does nothing to help us.

In this case, the client will POST the form unencrypted to your ssl_requirement protected action. ssl_requirement will determine that this particular action requires SSL, and sends a redirect to the HTTPS action, which the browser happily complies with. Unfortunately, at that point, it’s already too late, since the first transmission was unencrypted. Nothing breaks, and everything looks fine, but each and every form submission is being sent twice: once in the clear, and once with encryption. Not really what we wanted, right?

One solution is to always use named routes and set the protocol in the routing file. In this case, you must always use xxx_url (not xxx_path) in your form_for and form_tag calls. I have not personally verified that this works, but it seems like a decent solution.

Another way is to hack together alternate form_for and form_tag methods. These new helpers will test whether you’re currently in production or development mode and generate the HTTP or HTTPS form submission URLs accordingly. This is what we did for RioFlexPay, and it works fairly well.

In the end, we got rid of ssl_requirement altogether. It simply provided very little for us, and started to conflict with our Apache settings. In our case, we wanted the homepage to be unencrypted, but wanted all other pages to use SSL. This was fairly easy to set up with Apache rewrite rules. Unfortunately, this caused conflicts with ssl_requirement. The ssl_requirement plugin would see an action that wasn’t explicitly listed as allowing SSL and would redirect it to HTTP. Meanwhile, Apache would see an HTTP request for a non-homepage URI and redirect it to HTTPS. Thus, many of our actions resulted in infinite redirect loops, and of course we didn’t see this until we deployed to production, where SSL is enabled. Believe me, that was a late night of furious debugging. Simply removing ssl_requirement and allowing Apache to handle everything was our final solution.

So, just remember: ssl_requirement is not a magic bullet for SSL. You really have to step back and examine what you do and don’t want encrypted, and you need to think in terms of both client request and server response. Once you’ve decided on that, it’s time to make sure that your Apache rewrite rules, your ssl_requirement settings, and your link_to, form_for, and form_tag calls are all set up correctly. Only then can you rest easy.

My first Rails core contribution!

Ruby on Rails 2 Comments »

I just submitted my first Rails core patch! It was only a small issue dealing with a fairly unusual case (MySQL SSL connections), but heck, every patch counts, right? That’s how open source works.

It hasn’t been included yet, so I’ve got my fingers crossed…Wish me luck!

Connecting to MySQL using SSL encryption in Ruby on Rails

Ruby on Rails 17 Comments »

Recently for Obsidian Portal, we decided that we wanted to move some particularly intensive graphic processing offline from the main server. It was simply consuming too much CPU time and making the entire site sluggish. Luckily for us, it was already set up as a background process that only needed to connect to the database and Amazon S3. So, to do it on a whole new server wouldn’t require changing any of the algorithms.

However, since the remote server would be connecting to the main database over the Internet, we decided that encrypting the communication was probably a good idea. None of the actual data is all that sensitive, but the database username/password definitely is. Plus, in general, our policy is that any communication to and from our server should be encrypted.

It turns out that enabling SSL in MySQL is not too hard, but there are a lot of steps to follow. Further, to Rails docs on using database.yml to set up the connection aren’t that great (big surprise there). So, to help out those who are in the same boat, here’s what I did.

Setting up the MySQL server

The first thing to do is read through the official MySQL docs on SSL connections. These provide a good overview on how to configure the server to allow for (or force) encrypted connections. However, they assume a little knowledge of SSL and CA’s and keys and whatnot. So, if you’re stumped, you can read the following steps on how to proceed.

Verify that SSL is supported

We’re running Ubuntu on our server, and the MySQL that comes with it has SSL support already compiled in, so that’s a big relief on our part. I hate compiling from source, especially something big and important like MySQL.

To verify that support is already compiled in, log in with the mysql client and try the following:

show variables like ‘have_ssl’;

If it says DISABLED, then you’re in the right place. If it says YES, then you’ve already set the server up and can skip to the client or Rails sections below. If it says anything else (like no variables are returned) then it’s time to recompile MySQL. That’s beyond the scope here, but I wish you the best of luck.

Create the required SSL keys and certificates and whatnot

I’m no security expert, so all the SSL / CA / certificate / key advice is at your own risk. I’m still learning a lot of this stuff.

In order to get your server set up, you will need 3 files: A certification authority (CA), a certificate, and a key. Like I said, I really don’t know what all these things are. I just have a vague understanding.

To create my necessary files, I used TinyCA2, which I heavily recommend. It provides a GUI for using OpenSSL. Otherwise, get ready for lots of arcane command lines. If you’re on debian/ubuntu, all you need to do is run the following:

sudo apt-get install tinyca
tinyca2

Using TinyCA2, the process is a snap. It will walk you through creating a CA, then generating a certificate and key from that CA. I don’t know what options are required, but I got away with specifying only a common name for the CA and the certificate. Plus, I also used 1024 bit encryption since I’m not sure what level MySQL supports. I also heard somewhere that the common name for your CA and the certificate should be different, so watch out for that.

Once you’ve created your CA, certificate, and key, then you need to export them as pem files. In order to get MySQL to read the key, I had to export the key without a password. This is generally very bad advice, since if anyone gets the key they can pose as you. However, if the key is password locked, then MySQL would have to get the password from you somehow (Apache does this on startup), and maybe that’s just not supported. Please correct me if I’m wrong.

Configure MySQL to use the generated files

Copy the 3 files into /etc/mysql and then edit /etc/mysql/my.cnf Add the following lines:

ssl-ca=/etc/mysql/cacert.pem
ssl-cert=/etc/mysql/my-new-server-cert.pem
ssl-key=/etc/mysql/my-new-server-key.pem

Note! Make sure you check the file permissions to ensure that the mysql user can read the files. If you followed my previous bad advice and exported your key without a password, then it’s extremely important to strictly control the read permissions on these files. Chown them to the mysql user or use groups. Do not just chmod 777 and blissfully continue.

Restart your MySQL server and make sure there are no startup errors.

Test that everything works

The first thing to do is log in on the mysql client and check the have_ssl variable. Just run the following from the mysql client.

show variables like ‘have_ssl’;

If it says YES, then you’re good to go. If not, something went wrong and you need to retrace your steps to find out what’s up.

Client setup and testing

Now that the server is setup, let’s verify that we can connect with a client. The first thing to do is create a new user that only has SSL connection availability. Connect as root (or someone with grant privileges) and run the following:

GRANT ALL on somedatabase.* TO ‘ssluser’@'localhost’ IDENTIFIED BY ‘some_password’ REQUIRE SSL;

This will create a user that can only connect from localhost and must use SSL. Now, to make sure that everything is working, try this:

mysql -ussluser -p –ssl-ca=/etc/mysql/cacert.pem

If you are able to log in and don’t get the dreaded SSL ERROR message, then everything is great! If you do get an error, the first thing to check is the read permissions on the cacert.pem file. It must be readable by the current user. If your read permissions are set correctly and you’re still getting errors…sorry I can’t help. :(

Before we move on, it’s important to note that we’re using the same CA pem file as we did to create the server’s certificate and key. I really don’t understand why MySQL clients are required to specify a CA certificate, and I don’t know which are allowed. Presumably, you can set the server to allow clients to specify one of the major CAs (like Verisign or GoDaddy). Still, that’s beyond my knowledge. I tried creating a second CA and specifying that on the client side, but the server refused the connection. For now, it seems that you will simply have to copy the CA certificate to every remote client that wishes to connect to this server. That seems strange to me, and I’m probably wrong here. Please correct me in the comments.

Connecting from Rails

A small bump in the road…

The official Rails MysqlAdapter documentation lists the SSL parameters to use in database.yml. Unfortunately, the docs seem to be out of date and missing a very important parameter, sslca, the certificate authority file we need for every SSL client connection.

Further, the actual adapter code will not set any of the ssl parameters unless the sslkey option is set. This parameter is unnecessary in many cases, such as where you only want to require SSL communication and not X509 authentication of the client.

I have created a ticket and patch at lighthouse to cover this issue, but for now, you’re going to have to take a few extra steps to get things working.

Create a client key and certificate

While not strictly necessary according to MySQL, due to the coding of the Rails MySQL Adapter, you will need a client key and certificate. Like I said, I’ve submitted a patch, but no sense waiting on that.

Fire up TinyCA2 again and create a new certificate (select new client certificate and key) using the same CA that you used to create the server’s certificate and key. Again, export both the certificate (call it something like mysql-client-cert.pem) and the key (mysql-client-key.pem). Also, remember to export the key without a password!

Put these somewhere accessible to your Rails app. I will assume that you put them in the db directory. Make sure they are readable by your Rails app’s web server user.

Finally, place a copy of your cacert.pem in the db directory as well. Using TinyCA2, just go to the CA tab and click the export button. Drop in the db directory and check the file permissions.

Update your database user permissions

Update your Rails app’s user in mysql to give them remote access permissions. Assuming they are currently set to access only from localhost, the following line will extend access to your remote client.

GRANT ALL on my_rails_app_db.* TO ‘my_rails_app_db_user’@'my.remote.client.com’ IDENTIFIED BY ‘somepassword’ REQUIRE SSL;

Check your MySQL options and firewall

Make sure your firewall is set to allow incoming connections on the MySQL port (defaul 3306) and that your MySQL server is set to allow connections from more than just localhost.

Test using the bare mysql client

At this point, I would test that MySQL is accepting outside SSL connections by trying to connect using the mysql client from the remote machine. Something like:

mysql -umy_rails_app_db_user -psomepassword -hmy.mysql.server –ssl-ca=/path/to/rails/app/db/cacert.pem

If you cannot successfully connect using this, then you’ll need to troubleshoot your remote connection before trying to do anything with the Rails connection.

Update your database.yml

Add the following lines to your database.yml

sslca: /path/to/rails/app/db/cacert.pem
sslkey: /path/to/rails/app/db/mysql-client-key.pem
sslcert: /path/to/rails/app/db/mysql-client-cert.pem

Fire it up!

Fire up a Rails console on your remote client. If all goes well, you will be presented with the standard console prompt. You can verify that everything is working by executing the following

ActiveRecord::Base.connection.execute(“show status like ‘Ssl_cipher’;”).fetch_row

If you see something like DHE-RSA-AES256-SHA, then you’re set!

Congratulations! Your communications are now encrypted!

File summary

Since we’re dealing with so darn many pem files, I thought it might be nice to have an index of exactly which files you need and where you need them.

On the MySQL server

/etc/mysql/cacert.pem
/etc/mysql/mysql-server-cert.pem
/etc/mysql/mysql-server-key.pem
All files must be readable by the MySQL user

On the remote client

/path/to/rails/app/db/cacert.pem
/path/to/rails/app/db/mysql-client-key.pem
/path/to/rails/app/db/mysql-client-cert.pem
All files must be readable by the Rails webserver user

The cacert.pem files must be the same, and all the certificates and keys must be generated using the cacert (CA). In addition, the keys must be exported without passwords. Divert from this at your own risk!

Correct me please!

As I have said, I am not a security expert. If there is anything in here that is bad practice or just blatantly wrong, please correct me! The official documentation isn’t great, so it’s up to us (the community) to help each other out.

Help us climb

If you like this article, please link to it with the text AisleTen’s guide to connecting to MySQL using SSL encryption in Ruby on Rails. A few incoming links like that will help this article be near the top when people google for MySQL and SSL and Rails.

Hacking the Ultrasphinx plugin to work with paginating_find

Plugins, Ruby on Rails 1 Comment »

If you’ve been following our blog you may have noticed that we’re using Solr and ActsAsSolr plugin for our searching.

Getting started with acts_as_solr
acts_as_solr for development and production in one Tomcat instance
Optimizing Solr and Rails – Index in the background

Unfortunately being Java, Solr is a bit of a memory hog. We’ve attempted all sorts of optimizations, but we’re going to take a leap and switch to Sphinx. Sphinx is a free open-source SQL full-text search engine.

First step is to get Sphinx itself installed. For that have a look at Rob’s post:
http://www.notch8.com/articles/2007/10/15/sphinx-and-ultrasphinx-and-eye-on-search

Ultrasphinx works pretty much out of the box with will_paginate; however, a lot of our work is currently compatible with paginating_find. So to keep rails memory footprint down by using one plugin we’re sticking with paginating_find. Unfortunately Ultrasphinx doesn’t work out of the box with paginating_find, so time for a little hacking…

Install paginating_find plugin:

piston import http://svn.cardboardrocket.com/paginating_find/paginating_find vendor/plugins/paginating_find

More information on paginating_find

Install ultrasphinx plugin:

piston import http://fauna.rubyforge.org/svn/ultrasphinx/trunk/ vendor/plugins/ultrasphinx

More information on Ultrasphinx

Now for hacking Ultrasphinx plugin to work with Paginating Find plugin. Piston is great for managing plugins; however, it can easily get confused if you’ve hacked a plugin directly. The solution: use a method called “Evil Twin” as mentioned on the Err the Blog: Evil Twin Plugin

Create a directory for the hack:

mkdir vendor/plugins/ultrasphinx_hacks
touch vendor/plugins/ultrasphinx_hacks/init.rb

Now edit the vendor/plugins/ultrasphinx_hacks/init.rb file with the hacks for paginating_find:

# Hack to allow Ultrasphinx to work with pagination_find
Ultrasphinx::Search.module_eval do
def first_page
1
end

def last_page
self.page_count
end

def previous_page?
previous_page ? true : false
end

def next_page?
next_page ? true : false
end
end

Now for adding a method to your controller for the search:

app/controllers/posts_controller.rb

def search
@query = h(params[:query])
begin
@posts = Ultrasphinx::Search.new(:query => @query,
:class_names => ‘Post’,
:page => params[:page] || 1, :per_page => 20)
@ posts.run
rescue RuntimeError
flash[:warning] = ‘Search is currently disabled. Please try again in a few hours.’
rescue NoMethodError
flash[:notice] = ‘No records found for this search’
end
render :action => ‘list’
end

app/views/posts/list.html.erb

    < % @posts.each do |cog| %>

  • < %= posts.name %>
  • < % end %>

< %= paginating_links(@posts) %>

Paginating End Result

Bonus : will_paginate styled links

Unfortunately paginating_find doesn’t automatically have the “style” that will_paginate automatically comes with. So to fix that just add a little css for the style and a partial for the pervious and next buttons.

.pagination{
padding: 2px;
}
.pagination a, .pagination a:visited{
padding: 0 5px;
border: 1px solid #9aafe5;
text-decoration: none;
color: #2e6ab1;
}

.pagination a:hover, .pagination a:active{
border: 1px solid #2b66a5;
color: #000;
}

.pagination .currentpage{
font-weight: bold;
padding: 0 5px;
border: 1px solid navy;
background-color: #2e6ab1;
color: #FFF;
}

.pagination .disablepage{
padding: 0 5px;
border: 1px solid #929292;
color: #929292;
display: inline;
}

And now for the partial:

app/views/shared/_paginate.html.erb

< % if (collection.is_a?(PagingEnumerator) || collection.is_a?(Ultrasphinx::Search)) && (collection.page_count != collection.first_page) -%>

< % end -%>

So in your code replace the code paginating_links call with a render partial:

# OLD VERSION
< %= paginating_links(@posts) %>
# NEW VERSION
< %= render :partial => ‘shared/paginate’, :locals => {:collection => @posts} %>

Styled Paginating End Result

Resources:
ErrTheBlog: Evil Twin Plugin
Will Paginate Plugin
Paginating Find Plugin
Ultrasphinx
Sphinx

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in