Archive for April, 2010

Dynamic Named Routes for Semi-Static Pages in Rails

When I was designing the new UMSwing website, I had a few issues that, at the time, I didn’t have a clean method of implementing. One of those was the creation of semi-static pages. After watching this episode of Railscasts, I had a pretty good idea of how to implement them. The only issue with the solution offered was the lack of dynamically generated routes.

Semi-static pages are used everywhere on websites. They’re those pages like an “About” page, which has content on it that doesn’t really change that often. Typically, a controller would have to house these actions (/about, /faq, /contact, etc.), and  the routes specified manually. Railscasts came up with an ingenious idea to create a controller which was routed to /static/*, so that semi-static pages could be created on-the-fly and modified easily. It also allows for modifications to change without committing to a repository and going through the process of deploying all over again.

For those needing a quick Rails primer before going on, here’s the quick and dirty of what you need to know to understand this:

  • Rails is a MVC-based web application framework that runs on Ruby. In short, Ruby code is written to create webpages on-the-fly.
  • Every request in Rails is first put through the routes file in config/routes.rb. This file tells Rails which Controller and Action is run.

Okay, let’s get started. Let’s create our static pages scaffold (which includes model, views, and the controller). Obviously, there are sections of this that you would want to require authentication for (editing and deleting, for example), but that’s outside the scope of this tutorial.

script/generate scaffold pages title:string permalink:string content:text;
rake db:migrate

Now we need to modify our controller slightly. More specifically, our show action. Right now, it will respond to showing an element only when the ID is displayed. We want to modify it to handle a permalink as well (/about and /contact look better than /pages/135, don’t you think?). Here is your modified show action:

1
2
3
4
5
6
7
def show
  if params[:permalink]
    @page = Page.find_by_permalink(params[:permalink])
  else
    @page = Page.find(params[:id])
  end
end

Before we go any further, we need to create two custom methods in our model. These will format the permalink to remove any unwanted characters for the custom route name (replacing all unacceptable characters with an underscore) and for the URL (replacing all unacceptable characters with a forward slash to allow for nesting of pages). It’s also important to note here that previous validation should be done to ensure that the permalink does not have leading or tailing non-alphanumeric characters, but I removed that for simplicity’s sake.

1
2
3
4
5
6
7
8
9
10
class Page < ActiveRecord::Base
  def route_name
    p = self.permalink.gsub(/([^A-Za-z0-9])+/, '_').downcase # Change non-alphanumeric characters to an underscore
    "static_#{p}"
  end
 
  def uri
    self.permalink.gsub(/([^A-Za-z0-9])+/, '/').downcase # Change non-alphanumeric characters to a forward slash
  end
end

At this point, we can create and modify our pages as we would regularly expect from a new controller. All of our pages are accessible via /pages/1, /pages/2 etc. We now need to make our controller act as our catch-all (so that all requests that do not match any of the other controllers get routed to our Pages controller), and we also need to provide permalink support. Finally, we will dynamically generate customized, name routes for all of our semi-static pages. All of that gets accomplished with a few short lines of code. Add the following code to the top of your config/routes.rb file, starting at line 2 (inside the ActionController::Routing::Routes.draw section):

2
3
4
5
6
7
def map.static_page_actions
  pages = Page.find(:all)
  pages.each do |page|
    self.send("static_#{page.route_name}", "#{page.uri}", :controller => "Pages", :action => "show", :permalink => page.permalink)
  end
end

Finally, we need to call this method close to the bottom of the code, right before our default catch-all routes.

map.static_page_actions
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'

What this method does is retrieve all of the static pages in the database, then creates a customized, named route for each page, telling Rails what each URI should look like, and where to direct the request to.

Hopefully this helps some people out with their dynamic page creation. I’m pretty sure there’s a pitfall or two here, but I think it could be taken care of by doing some simple route housecleaning in the Pages CRUD controller. The perk of this option is that it allows the routes to be named, and hopefully that is of some benefit for others.

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Reddit

Fix Your Facebook Privacy Settings

Earlier this week, Facebook rolled out a new privacy policy which allows outside applications to view information stored on you, including your likes, connections, education, current city, and more. Needless to say, there’s a big issue with privacy here. While you want your friends to be able to see this information, you want to avoid giving it to 3rd parties as much as possible. Here’s some key tips to locking down your profile from those automated prying eyes.

1. Remove Instant Personalization [link]

Instant personalization gives your information to 3rd party websites such as Docs.com, Pandora, and Yelp. Uncheck this box to prevent these sites from accessing your information.

2. Remove Unused (and sketchy) Applications [link]

Chances are you’ve added some application at some point, and although you deleted it off your profile, it probably still has access to your profile. Remove any unwanted applications by going to the link above and deleting those apps which shouldn’t be there. You might be surprised how many pages can see your information!

3. Remove Your Public Profile [link]

Data mining will largely rely on your public profile as a starting point for gathering your information. Remove that ability by going to the link above. Change your Facebook Search Results to Friends and Networks, and then Uncheck the option to have a public profile.

4. Lock Down Your Contact Information [link]

On this page, you can find all of the contact methods that are available to you. Unless you really want anybody to contact you, it is best to set almost all of these to “Friends” and nothing else. The only exceptions are the option to add you as a friend, and to send you messages. Both are worthwhile to leave open to everybody unless you happen to get spam from them.

5. Lock Down Your Profile Information [link]

Finally, there’s your actual profile information that should be locked down. Setting all of these to “Only Friends” is the best course of action.

If you haven’t done so, lock down your information soon. I can guarantee that the automated data mining services are working full-tilt in case Facebook reverts its privacy settings. It’s time to take control of your profile settings.

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Reddit
Return top