I just got back from the first Misoula BarCamp, and I think it was a success. We had about 18 people show up, which I think is very good for the first one. One attendee ( a fellow Rails developer ) came all the way from Helena. There were also some people that I was hoping/expecting would be there that weren't so hopefully they'll come to the next, whenever that is. There was a great mix of technical and non-technical discussions and presentations (I gave a little Rails demo). At any rate, big shout out and thanks to Harold for putting the whole thing together. I don't think anybody who went was the least bit disappointed in doing so, despite missing out on the first really nice spring weather in a couple weeks.

Free Image Hosting by FreeImageHosting.net
A few of the attendees looking over the topics board to
pick out which sessions they're going to go to.
Comments: 2

I've noticed in my site logs people are searching the Interweb Tubes for "GateKeeper" combined with other keywords that suggest they're looking for some better examples on how to use it, so I figured maybe I'd write something up to try to help.

GateKeeper is a Ruby on Rails plugin providing a natural language DSL to manage security permissions on instances of ActiveRecord classes at the Model level. Permissions may be assigned based on the current users roles, and/or by their relationships to the object in question. GateKeeper automatically intercepts all attempts to CRUD (Create, Read, Update & Destroy) instances of ActiveRecord classes and verifies the current user has permission before allowing the operation to proceed.

The main requirement of GateKeeper is that it expects that you have a 'User' class, and that it responds to the class method 'current', as in 'User.current'. If you need to use a different class (such as 'Person' or something), that can be defined in your environment.rb, but whatever it's called, it must respond to 'current' and return an object that represents the currently logged in user. So, here's a simple example of how to set that up.

Exactly how you get your users logged in is up to you and still beyond the scope of this post, but I'd recommend a SessionsController and a User.login(username, password) method. So, we'll assume that you have that setup already and that you store the 'id' of the currently logged in user in session, such as 'session[:user_id]'.

The first thing you'll want to do is have a method in your application controller that sets up the current user for the rest of the application...

class ApplicationController < ActionController::Base
  before_filter :setup_user

  def setup_user
    User.current = User.find(session[:user_id])
  end
end

Now, we need to add 'current' and 'current=' methods to User.

class User < ActiveRecord::Base
  
  ## Class Methods ##
  class << self
    
    def current
      @CURRENT_USER || User.new(:username => 'guest')
    end

    def current=(u)
      @CURRENT_USER = u
    end

  end

end

And that's it for User.current. Now, anywhere in your application (Models, Controllers, Helpers, and Views), you can just call User.current, and get an object that represents the currently logged in user. Now we'll go into some basic uses of GateKeeper.

If users can register new accounts on your site, then you'll need to allow 'guest' users permission to create new users. Update your User class with the following (previously shown class methods left out for brevity).

class User < ActiveRecord::Base
  ## Permissions ##
  creatable_by_guest
  #################

  def is_guest?
    username == 'guest'
  end
end

However, if at any point your application tries to save the current user, it could potentially end up creating a user with the username 'guest', which you probably don't want. So, update the above with the following...

  ## Permissions ##
  creatable_by_guest :unless => lambda {|new_user| new_user.is_guest? }
  #################

The 'is_guest?' method above is an example of how to define dynamic 'user roles' for GateKeeper. When you say 'creatable_by_guest', GateKeeper expects to either find a 'is_guest?' instance method on User, or a Role named 'guest' belonging to User.current (see below). Here are some examples of other dynamic user roles that you might want to define for your users.

class User < ActiveRecord::Base
  def is_premium_member?
    premium_membership_expires_on > Time.now
  end
  
  def is_logged_in_user?
    !is_guest?
  end

  def is_popular_user?
    popularity_ratings.size > 42
  end
end

class Foo < ActiveRecord::Base
  ## Permissions ##
  creatable_by_premium_member
  updatable_by_popular_user
  readable_by_logged_in_user
  #################
end

As I stated above, GateKeeper also looks for a Role belonging to User.current with the name of the Role used in the permission. To set this up, you'll want the following...

class CreateRoles < ActiveRecord::Migration
  def self.up
    create_table :roles do |t|
      t.string :name
      t.timestamps
    end
    add_index :roles, :name
    
    create_table :roles_users, :id => false do |t|
      t.integer :user_id
      t.integer :role_id
    end
    add_index :roles_users, :user_id
  end

  def self.down
    drop_table :roles
    drop_table :roles_users
  end
end

class User < ActiveRecord::Base
  has_and_belongs_to_many :roles
end

class Role < ActiveRecord::Base
  has_and_belongs_to_many :users
end

Now, if you were to create a role named 'moderator', and assign it to a few of your users, you could give those users special permissions on certain models, such as updatable_by_moderator . Take note that the role name should be all lower case and underscored so that your permissions look nice. If you have a role named 'SpecialUser', then your permissions would need look like 'readable_by_SpecialUser' which isn't beautiful code, and if the role name has spaces in it, it won't work with GateKeeper at all. 'special_user' is a much more appropriate role name for GateKeeper's purposes.

So, there you have it. I hope that helps some people get over the initial hurdle of setting up GateKeeper. I'd love to hear from anyone using GateKeeper and hear your thoughts and questions.

Comments: 0 [add comment]

That horrific piece of propagandist trash by Ben Stein disguised as a hard hitting documentary that makes Michael Moore look like Jacque Cousteau came out today, and the official reviews are finally coming in...

You know that flatulence like sound that balloons make when you let the air out and the last bit finally escapes before it goes completely limp? That's the sound that Ben Stein's career is making right now. But if you still feel compelled to go see this garbage, here's one more site about --> Expelled <-- that you should read first (created by the National Center for Science Education), and be sure that you offset your price of admission with a truth ticket or two... or three... dozen.

Comments: 0 [add comment]

I've just released ARID 0.5. This is a minor update with some small bug fixes and optimizations.

ARID ( ActiveResourceIntegrationDsl ) is a Ruby on Rails plugin offering easy to use methods for writing integration tests on RESTful Rails apps. With ARID you write simple statements like user.builds_article(:params => {:article => {:subject => 'Hey!', :content => 'Hello World!'}}) which will GET your new_article_path, check that it has a properly formatted form with fields for all the given params, and then will POST the params to articles_path and assert the expected response. You can even pass a block to the above call to perform additional tests. And YES, ARID tests AJAX calls.

More info and installation instructions at http://arid.rubyforge.org.

Comments: 0 [add comment]

I've just release version 0.3.1 of Cross Site Sniper. This is a minor bug fix update.

Cross Site Sniper is a Ruby on Rails plugin that automatically html escapes all string and text fields of ActiveRecord objects. Data is escaped as it is retrieved from the database to protect your site from XSS (cross site scripting) attacks without modifying or corrupting your original data. Convenience methods are provided to access the unescaped data when necessary. Edit forms are prepopulated with unescaped data as well to avoid user confusion and prevent double escaping.

Documentation and install instructions can be found at http://xss.rubyforge.org.

Comments: 0 [add comment]

And I'm going to stay this way all day long! In honor of "CSS Naked Day", 5Valleys is going to spend the day lounging around the web in the nude.

I don't consider myself anything remotely close to a designer. My aesthetic eye is completely non-existent (anybody who's seen me try to dress myself knows this). Which is why, once I grasped an understanding of the full power of CSS and learned how to set up a CSS friendly site, I came to really appreciate CSS. This way, I can turn over the beautification of the site (not this one specifically, this crap is all my doing) to a talented designer who can just work some CSS magic and make it all pretty.

Therefore, to help draw attention to CSS and promote web standards, 5Valleys is joining hundreds (thousands?) of other websites around the web, and turning off it's CSS for the day. See who's all playing along at the CSS Naked Day page. My apologies to those who followed a link here hoping to see a picture of me with my Johnson swinging in the breeze. Maybe next year.

Comments: 0 [add comment]

The Obama Rally in Missoula this morning was fun and memorable. It was definitely worthwhile to be able to participate in such a historic event. I got there a little after 8 this morning and was amazed to see how long the line was already. I could see it stretching from the front door all the way back past the Montana Theater and to the end of the next building at the end of the block. I called some friends to see if they were already in line in hopes of being able to cut in line with them. They answered and replied that they were in line in front of the University Theater. "Dummy," I thought to myself, "that's not the University Theater.. that's the Montana Theater. The University Theater way down around the corner a couple blocks." But, no... he was right, they were in front of the University Theater... and they weren't even close to the end of the line. The line wound around from there and back on itself up and down several blocks. My unscientific guess is that the line maxed out at about 12 blocks long when it finally started moving.

Anyway, we managed to get some really good seats, and I managed to get almost the entire speech on video, which I'm now trying to get uploaded to youtube in 5 parts. The links to each are below (or will be once I get them all uploaded.) My camera's memory card decided that it had had enough politics for one day just seconds before the end of the speech, so that's where my footage ends. He was just wrapping up at that point though, so nothing of substance was missed.

Comments: 2

As recently as just a couple years ago, I didn't "get" RSS feeds. I understood the general concept, but I didn't understand WHY. What's the point? Why all the hubub? Then one day, it just clicked. RSS feeds allow me to be notified that a particular website I'm interested in has been updated with new content, without having to remember to browse to the site everyday to check for myself, and without (this is the kicker) having to give them my email address. When I don't want to get updates anymore, I just cancel the feed on my end. No need to figure out what hoops I'm supposed to jump through on their site to try to unsubscribe, no worries about them selling my address to a spammer, nothing. I have complete control... as long as the site provides an RSS feed (which a couple years ago, not that many did).

Now, two years later, I can't believe that some sites STILL don't provide RSS feeds. Case in point... the Missoulian. This is a website for a newspaper! They have updates every day, but I really don't want to have to remember to go check their website every day (which I don't and that's why I rarely go there) and I don't want to have to wade through a bunch of garbage on the site to see what's new. I just want a simple list of headlines to automatically show up on my computer as they become available, and I want to be able to click any that interest me to go right to the full story at the Missoulian. This is the 21st Century. This is how news gets distributed now. Everybody from The New York Times to I Can Has Cheezburger? have RSS feeds now, but the Missoulian? Noooooo... well, until now. But not becuase they did anything about it.

I finally got fed up with not being able to keep up on the local news as easily as I could on the national and international news. So, I wrote a little Ruby script to figure out what the latest stories and breaking news was at the Missoulians website, and format it into a couple RSS feeds. And, because (as I've said before), "you're all that, and more," I'm giving it to you, too.

One word of warning, though. The underlying HTML at the Missoulian has the consistency and structure of potato salad, making it very difficult to programatically figure out where the news stories are inside the mess, and therefore any little change they make to their site could easily break the feed. Considering they should be seriously thinking about redesigning their site anyway, it's only a matter of time before this happens. Or, maybe not... who knows. Anyway, if the feed breaks, I'll see about fixing it as soon as I damn well feel like it... until they start paying me for the service.

So, without further ado, here's the links for the feeds. Copy and paste the URLs into your favorite feed reader. And post a comment here to let me know how you like them.

Another thing that I didn't really "get" until recently were Podcasts. Podcasts are like RSS feeds (in fact, they are RSS feeds), but instead of delivering text and a link off to some news site or blog, they provide a link to an mp3 file that your computer automatically downloads for you. When people hear mp3 they often think "music" but podcasts are usually just people talking, and the first ones I ever tried to listen to were people who really, really liked to hear themselves talk and who didn't say anything I was particularly interested in listening to. Which is why I didn't "get" it. "Why the hell do people want to listen to this crap?" I asked myself. A great many (maybe even most) are still like that. But I've come to realize that hidden among all the garbage are a few really, really good gems. Podcasts get their name from iPods, but you do NOT need an iPod to subscribe or listen to them. Any podcast client (google for it) that you can install on your computer will do, although having a convienent way to move them onto an mp3 player to so you can listen to them, for instance, while driving to work, mowing the lawn, and so on is extra nice. It's kinda like TIVO for internet talk radio.

So, anyway. While working on the above RSS feeds, I had an idea. KUFM, the local Public Radio station posts the evening news as an mp3 file on their site, but it's not a podcast. While I'm doing these RSS feeds for the Missoulian, why don't I turn that news into a podcast for KUFM? Then I can listen to the previous nights news while on my bike on my way to work the next morning! So... I did that too, and again, since you're all that, and more.... (note: they seem to be having some audio issues with the last couple episodes, but my tests for last weeks shows worked fine, so as soon as they solve that, this should work great.)

And to close things off, Here's a short list of some of my absolute favorite podcasts. Load your mp3 player up with these, and like me, you may never want to turn your TV on again.

Comments: 0 [add comment]

Obama and BarCamp are coming to Missoula. Thankfully, not on the same day.

Thanks to my new Missoulian RSS Feed (what? huh? move along, nothing to see here... next post on that subject) I just found out that Presidential Candidate Barack Obama is having a free rally at the Adams Center Saturday morning. I'd be there even if it was Bush III, I mean John McCain. This is history in the making folks!

And on a completely unrelated note, Missoula is having it's own BarCamp on April 26th (also a Saturday). What's a BarCamp? According to Wikipedia....

BarCamp is an international network of user generated conferences — open, participatory workshop-events, whose content is provided by participants — often focusing on early-stage web applications, and related open source technologies, social protocols, and open data formats.

The official site for Missoula's contribution is at http://missoulabarcamp.org. Registration is required. Early registration recommended. I hope to see a great turnout of Missoula's Tech Professionals.

Comments: 0 [add comment]