You are viewing a read-only archive of the Blogs.Harvard network. Learn more.

Holy Crap!

It’s Thanksgiving. I swear that September through January is always a god damn blur. Every now and again I’ll lift my head up, shout out some expletive and then get back to the business of getting through the holiday season.

At this rate, I’ve averaging one railscast per month. Considering that Ryan churns out at least one a week, my project doesn’t appear to be progressing as I’d hoped.

But hey, I have photos to make up for it.

Happy Halloween

1 comment November 24th, 2010

Our Little Secret

So wading through every single Railscast episode isn’t going as well as I had planned. Life keeps getting in the way. October is a very busy month. Halloween is very important to me and my family. And yes I do spend all month getting ready. Truthfully, I’ve been getting ready since August.

You do know that my brother is a horror filmmaker out in LA, right? Yup. Halloween is a busy time of year. And the theatrically of it all is just too hard for me to pass up.

In addition, it’s hard to stay focused on getting through these early episodes when more exciting things keep jumping out at me…. like the JQuery Conference this weekend. A whole lot of awesome.

But whether it takes a year or longer, I’ve made a commitment and I plan to stick to it. So, I’m combining three episodes once again into one blog post. They’re all related anyway. And I have a feeling that Ryan likely wrote this as one episode initially and then broke it out into three because he was busy as well. Shhh. It’s just our little secret, Ryan.

So, this threesome is more about security. Bottom line:

params  <-- don't trust it
cookies <-- don't trust it
session  <-- you can trust it

SQL INJECTION: Episode 25

When the dev places the user input directly into an SQL query, there is potential to really mess up the db.

This is BAD:

@tasks = Task.find(:all,:conditions=>"name LIKE ’%#{params[:query]}%’")

Input a quote and everything after that is considered pure SQL.

if params[:query] = " ' " + "DROP DATABASE"
YOU ARE F*CKED
end

There are easy ways to escape conditions.

tasks = Task.find(:all, :conditions=> [ "name LIKE ?", "%#{params[:query]}%" ]

This still looks dangerous to me but Rails will actually escape this for you. You only need to worry about escaping input in find methods if you’re using the :conditions parameter. If you’re using the dynamic find_by methods then Rails will automatically escape any input which will ensure that you’re safe from SQL injection.

So Ryan, you’re saying that the code below is safe?

tasks = Task.find_by_name(params[:query])

Really? Let’s try it out.

query = " ' " + "DROP DATABASE"
tasks = Task.find_by_name(query)

Whew! I still got my db. ;-)

MASS ASSIGNMENT: Episode 26

@user = User.new(params[:user])

Everything in the params[:user] hash is being sent to create the user record. Don’t ever trust the params hash. It could be anything.

One way to prevent problems is to set protection on your user model. attr_protected will disable mass assignment for the fields you want to protect.

So in Ryan’s example, he had a User model with a boolean field denoting whether or not a user is an admin. By setting attr_protected :admin in your user model, you’re preventing the admin field from being set.

Here’s another example:
stuff = {:login => "Hacker", :password => "hacked"}
@user = User.new(stuff)

When attr_protected :password is set, the code above will not update the password field. But this will:

@user.password = 'goodsecurity'

So, that’s good. But actually, its better practice to use attr_accessible to open the fields that you want to be set via mass assignment and automatically hide all the rest. This protects fields that can be set indirectly via associations.

CROSS SITE SCRIPTING: Episode 27

Allowing the user to input nastiness to the site directly is bad news. Adding data to a table directly from a view is fraught with issues. Ryan shows an awesome example of this. Try going to your favorite insecure website and type in any input text box:

I can haz hack? alert('i haz hakked u')

If you see an alert box, then this site is vulnerable to Cross Site Scripting. To avoid this problem, you need to escape user input. In older version of rails, you needed to use h method.

Really annoying to have to remember to add h to all your views. Another way to do this is to sanitize the input in the controller. Perhaps best to do it in both places. Or better yet, upgrade to Rails 3.

Rails 3 adds XSS protection by default. This means that you no longer have to manually escape user input with the h helper, because Rails will automatically escape it for you.

IT’S ABOUT TIME!!

But if you really wanna protect yourself, use html_safe. You can read up all about it and more on Yehuda’s blog: SafeBuffers and Rails 3.0.

Hey, let’s be careful out there.

October 20th, 2010

Debugging Unicorns and Rainbows

This is a favorite topic of mine. Maybe it’s just me, but it feels like all the other rubyists out there get to work on fresh code bases that are well tested using all the latest tools.

Well, sadly, that’s not my situation. We’re on Rails 1.2. Yeah. And tests? Well we’ve got them. And at one time they actually worked. *sigh*

So, debugging is very important to me. And in episode #24, Ryan tells how to decode the stack trace. And this is a very valuable resource. But honestly, I couldn’t survive without my IDE debugger.

Now, apparently no self respecting rubyist uses a debugger. First reaction I get from folks is, “We have tests”. Well, yay for you. Then I hear, “Well, you can always use script/console and puts statements.” And indeed, this is very helpful.

For example, you have the simple method below:

def my_broken_method(greeting)
greeting + ', ' + User.current.login
end

Let’s say you’re getting an unexpected name and want to checkout what User.current is really returning. Well, just add a puts like this:

def my_broken_method(greeting)
puts User.current
greeting + ', ' + User.current
end

And then from the command line you call script/console:

>> script/console
>> my_broken_method('Hello')

You should see something like:

#"2010-04-28 14:40:49.277067-04", "updated_at"=>"2010-09-28 17:18:25.755037-04""firstname"=>"Liana", "password"=>"ff1ec54a58581b7aa7ce3e9c9ee93c3599ae", "login"=>"lleahy"}>
=> "Hello, lleahy"

And from this, I can tell that I may actually want to use User.current.firstname instead of User.current.login.

Now this is okay for simple, direct debugging. I use it all the time. But sometimes you need to step through code, line by line to track down a problem. And when things get really scary, I rely on my trusty debugger.

Command line enthusiasts will sometimes use ruby-debug. This tool will allow you to “set a breakpoint, inspect variables, change the code and more”.

If this works for you, great. Me? I’m a visual, gui kind of gal. I’m not afraid to admit it. Yeah, I took the Vim class. And I do use vim when I’m working on the server. But for intensive programming I simply prefer using Netbeans.

I got started with Netbeans back when I was stuck on a Windows machine and couldn’t get my hands on Textmate. And since then, I’ve grown so attached to my debugger (and the visual source control cues that rock hard) that I can’t seem to ween myself off an IDE no matter how many plugins I try to integrate into vim.

Truth is, it doesn’t matter which tool you use as long as you use it productively. Likely, I’ll eventually switch to vim because somehow I’m “less than” because I don’t live my life on the command line. Doesn’t matter that I can write up a scary sql query with double digit table joins before you can say ‘foreign key’.

Sure the gui tools can be a crutch but as long as I understand the magic beneath, why can’t I have my unicorns and rainbows?

September 28th, 2010

INCREDULOSITY!

Adding a counter to your models is a nifty little rails feature that requires very little setup. One more reason to revisit these old episodes is a little gem tossed in to episode #23.

The pluralize method. Rails does its pluralizations with the Inflector class. You can read all about it from Amy Hoy:

Rails’ use of pluralization is pretty smart, albeit not perfect. From “person” you get “people,” and “mouse” you get “mice.” If you’re tracking deer, though, watch out for “deers.”

Here are a few of her examples:
Inflector.pluralize('test') => "tests"
Inflector.pluralize('mouse') => "mice"
Inflector.pluralize('geese') => "geeses"
"mouse".pluralize => "mice"
exit 1.ordinalize => "1st"

Amy Hoy is wicked cool and one of my ror rockstar role models.

Wait wait—code AND design chops? INCREDULOSITY!

September 20th, 2010

Everyone Poops

We all know that hitting the database as little as possible is one of the keys to improved performance. But rails can sometimes feel like a magic unicorn you don’t want to touch lest it fade into the mist.

Go ahead. Look that gift horse in the mouth. Even Unicorns poop and it’s all there in your development log.

Sorry for the poop comment. We’re potty training at my house.

But in keeping with the poop theme here, there’s a lot of valuable information in your output.

In episode 22, Ryan shows us eager loading. By using :include in your finders, you can squeeze multiple queries into one. So take a second look at those loops and check out that dot notation.

There are other ways of joining on tables, such as using :join. Which makes me wonder. Any other examples of ways to take advantage of eager loading?

September 10th, 2010

A Rant

The market is really tight for ruby developers in Boston. Companies are often complaining that there is no talent to be found. But I think that’s mostly because companies are mainly looking for rockstars. And there are few of those to go around.

I understand that tech teams for startups need to be lean and effective, but if Boston rubyists want the community to grow they are going to need to convince their companies to invest in mentoring intermediate level programmers or even advanced beginners with solid experience in other realms.

Because I’ll tell ya, refining your skills on your own time after work is… hard. And as much as I try to find motivation through crazy ideas like the Railscasts Project and posting my little FaceBook app side project to github, I have commitments (my little girl) and obligations (my little boy) that demand my attention away from my laptop.

Is there really a work life balance for the ruby developer when the language and tools are evolving at such a frenetic pace? How the hell do these cowboys keep on top of it all?

Maybe they don’t know everything and just pretend they do… That’s a boy quality, isn’t it? And quite possibly, I know more than I may portray… That’s a girl quality, isn’t it?

How come I always feel like I just missed bus? (That’s a human quality, isn’t it?) Does anyone else feel this way?

The boston.rb community has been discussing various mentoring programs that they’d like to create. And I’m down for that. But honestly, I don’t believe it’s possible to learn how to speak French once a week and after the kids go to bed.

To become a true Parisian, don’t you have to go to France and immerse yourself in the language and the culture and the food?  So, isn’t it mandatory for the aspiring rockstar to work with a development team during office hours that practices agile slicing and dicing and are dedicated to testing and tasting their work, who ladle gems and libraries down their gullets like a sweet, creme based soup?

“That seelly Amerreecan weell neverr be eh true Parisian. No!”

I’m thankful to have a job that let’s me play with ror every day. Still, I wish more companies felt like @dpickett who recently tweeted:

I would place my bets on enthusiasm over talent any day. Invest in those that want to learn instead of those who think they know everything.

September 9th, 2010

Squashing

I laugh at my naiveté thinking that I could get any work done during vacation week with my two toddlers. Surely, I could watch and blog one episode a night? Surely?

Ha ha ha! Once my eldest was finally coaxed, cajoled and threatened into staying in her bed for the evening, I was a puddle of exhaustion without enough energy to even lift a martini glass to my lips. And if you are familiar with my relationship to vodka, you’ll realize how god damned tired this really is.

But today, the kids are back in school and I’m back at work… and it’s September. For me, this is a time of renewal… of starting over with a clean slate. And so…

The theme of the day is “squashing”.

Just before vacation, I completed a huge enhancement on a branch with pages and pages of commits made over a period of months. Helpful to me while I was in progress, but now that the work is complete… well it’s just plain too ugly to commit back to master. How many commits were there? I used this command to count them:
git log --pretty=oneline origin..mybranch | wc -l

Whoa. 61 commits for one enhancement. But thankfully I can use this tutorial from Bob Silverberg to use git rebase and squash all these commits into one.  Making my git log clean and neat.  And I like clean and neat.

So in keeping with this theme, I’m squashing the next three Railscast episodes which are all about creating administration screens.

“Why separate the public site from the administration side?”…Why indeed, Ryan. Scaffold generates new and edit views for my model, and episodes 19-21 shows us how to restrict access to them.

One railscast fan had an interesting question about this implementation:

This approach is pretty useful, but won’t it complicate caching down the line?

And Ryan’s answer:

True, it can make caching a little more difficult. A solution that I like is to create an “admin” subdomain for the site (admin.example.com) then just have the “admin?” method return true for this subdomain. This way you can easily cache pages without this subdomain.

What’s interesting about episode 20 is that Ryan shows us that a method implemented in the Application Controller can be used in a view via the helper_method method.  And then he goes on to introduce the before_filter.

Filters are pretty handy as demonstrated by this example.  But I’ve also seen filters abused horribly making it difficult for the maintenance programmer to track the flow of logic in an application.  As with everything, moderation is key.

In the final episode of the series, number 21, we learn about the restful_authentication plugin.

Back in the day… I implemented this plugin in a production app using the Restful Authentication with all the bells and whistles tutorial. But in 2010, we’ve got Authlogic, Clearance and other solutions for our authentication needs.

Yeah, okay… so these solutions might be much more than you need for a simple site. If so, use Ryan’s session example. But most plugins are so easy to implement! In fact, you can find an Authlogic starter application that includes Facebook integration. I’ve used it. Works awesome.

I prefer to use Authlogic even on my most simple sites because inevitably the client wants more functionality. And as I mentioned in my Security blog, I prefer to leave security management to the pros.

September 8th, 2010

Not Giving Up!

Oh Geek Mama… Why o why have you forsaken the Railscasts project? Is it your homage to _why last week?

No. I haven’t given up! I swear I haven’t! Big project at work. Working all weekend. Up until wee hours. Exhausted.

But I won’t let that stop me. Just slow me a down a little bit. But this week I’m getting myself back on track…. just in time for my planned vacation at the end of the month. Yay.

Ain’t nothing gonna break my stride
Nobody’s gonna slow me down
Oh no, I’ve got to keep on moving
Ain’t nothing gonna break my stride
I’m running and I won’t touch ground
Oh no, I’ve got to keep on moving

Yes. I admit it. I wanted to grow up to be a Solid Gold dancer.

August 23rd, 2010

A Show of Hands

Okay, people. I want a show of hands from everyone is Looping Through Flash messages as shown in episode #18:

    <% flash.each do |key, msg| %>
      <%= content_tag :div, msg, :id => key %>
    <% end %>

Instead of simply using the scaffold default which looks like this:

    <% unless flash[:error].nil? %>
      <div id="error"><%= flash[:error] %></div>
    <% end %>
    <% unless flash[:notice].nil? %>
      <div id="notice"><%= flash[:notice] %></div>
    <% end %>

I can’t say that I’ve ever seen Ryan’s example in the wild. In fact, I’m not even ashamed to admit that I”ve never seen anyone use the content_tag to create div tags in a view. Have you?

Admit it. You’ve forgotten all about content_tag. Damn, I’m glad I didn’t skip these early episodes!

August 17th, 2010

What Genius Created Checkboxes?

Good workout. Thanks for asking. Felt so yummy to be back in the gym. Wish my husband didn’t have evening clients so I could do it more often.

Unfortunately, my husband’s sporadic schedule combined with my kids’ relentless bedtime ritual means it’s impossible for me to keep a regimen going. Which is really ironic when you consider that he’s a personal trainer.

Anyway, back to rails related stuff…. I am freaking amazed how I learn something new with each episode. Tonight, I watched episode #17: HABTM (Has And Belongs To Many) Checkboxes.

Did you know that simply passing an array of values to your foreign key will auto-populate your join table? Ryan’s example illustrates this nicely via script/console:

>> p = Product.find(:first)
>> p.category_ids = [2, 3]

This code above automatically created the SQL insert statement below:

INSERT INTO categories_products('product_id', 'category_id') 
VALUES(1, 2)

Of course this only works with HABTM. You’re outta luck with Has Many Through and gotta roll your own. Still, this little shortcut is kinda nifty.

By the way… don’t you just HATE that empty checkboxes return NOTHING in HTML. In other words, when the checkbox is not checked no value is sent.

What a PAIN IN THE ASS! Sure there are ways to get around this, but what genius thought this up?

Yeah okay, there’s most likely some serious reason why this must be… but all I know is that I have to jump through stupid hoops and make an extra database call to get this to work properly. LAME!

4 comments August 16th, 2010

Next Posts Previous Posts


Pages

Tweets

Meta

Recent Posts