How to limit users to one vote per IP address

Standard

A reader Aaron J. writes in response to the short article How to obtain the IP address of the current user:

Do you have any advice on how I can take this a step further? I am looking to limit a given user to one vote per session but I’m not sure how to achieve this. I’d appreciate any help you can offer. Thanks for your time.

Good question, Aaron. Remember that a session is simply tied to your browser cookie, so if we allow one vote per session, all the user has to do is clear their cookies and then vote again. And again. And again! So I think what you mean is how do we allow only one vote per IP address? To enforce that, we’ll need to save a list of the IP addresses that have already sent us a vote. And before we record a vote, we need to make sure their IP address isn’t already on that list. Further, we should remember which poll number they have voted in so we can have more than one poll in our application. We’re going to need a simple table:

# lib/db/migrate/001_voter_log.rb
create_table :vote_log do |t|
  t.column :poll_id, :integer
  t.column :client_ip, :string
end

For simplicity of this example, we’ll put all of our logic in the controller. (I won’t show the VoteLog model class because it’s empty.)

# RAILS_ROOT/app/controllers/poll_controller.rb
def record_a_vote
  poll_id = params[:poll_id]
  client_ip = request.remote_ip

  unless VoteLog.count(:all, :conditions => ['poll_id = ? AND client_ip = ?', poll_id, client_ip]) == 0
    redirect_to :already_voted
  end

  Poll.find(poll_id).record_vote(params[:candidate]) # Or however you count votes
  VoteLog.create(:poll_id => poll_id, :client_ip => client_ip)
end

def already_voted
  render :text => "You already voted, no cheating!"
end

Just keep in mind this approach might not be appropriate in all situations. Due to Network Address Translation (NAT) firewalls, many thousands of people will appear to have the same client_ip. This is particularly true in corporate environments. If that’s a concern, you’ll need to go with a full-blown registered-user approach.

Further Reading

How to obtain the IP address of the current user

Feedback and Article Ideas

Want to see a topic explored here? Send Me a Message.

Ruby, Rails and hash’s with_indifferent_access

Standard

Long Names

Ruby developers like to be clear in their naming of variables, modules, classes, methods, and so on. I believe this comes from the idea that code should need very few inline comments if it is written clearly and descriptively. This descriptive naming strategy, combined with the decidedly non-English origins of Ruby (Japanese) and Rails (Danish), often result in oddly-named creations such as #execute_query_as_logged_in_user_without_transaction_logging (which I just made up), and #validates_numericality_of (which is real).

A newcomer might find these tongue-twisting, hyper-descriptive naming conventions maddening, but most of the time the intent becomes so much clearer as a result, it becomes infectious; in no time you find yourself writing your own 30-letter, borderline-semantically-correct method names and producing highly maintainable, readable, self-documenting code. That doesn’t mean it happens all the time, though…

Continue reading

Thanksgiving: Thanks for Radio Lab

Standard

8C3343F4-4489-48A2-92AD-AD00CCE923E4.jpg

While getting fat on turkey and mashed potatoes in Minnesota over the holiday, I discovered a great little radio show called Radio Lab, which is also published as a podcast. I had originally heard a clip of their show on This American Life a couple months ago, but despite Ira Glass’s ringing endorsement, I hadn’t sought out a listen until the night before flying. Boy, am I glad I did.

What’s Radio Lab? Think Car Talk (but more production and no phone calls) meets Bill Nye the Science Guy. What I like about the show is that the topics are science-focused, and the hosts (Jad and Robert) banter and discuss things in a lively way. It’s not boring; rather, it’s engaging and the pace moves swiftly. The production seems almost built for the attention-deficit world we live in: some key phrases are repeated for emphasis, there is some narration on top of recorded stories to provide clarification, and there is discussion in a conversational tone. It all adds up to a really fun and enlightening experience.

I managed to listen to eleven podcasts on four flights and while drifting off to sleep each night over the last few days. If you’re looking for a place to start, my favorite episodes so far have been Morality, Musical Language, Memory and Forgetting, and Who Am I?. It’s a fairly deep-thinking, hour-long show, so I’m not sure how it would hold up under the demands of driving (I often find my mind wanders as I drive regardless of what I listen to). But if you can manage to concentrate fully and follow along, you’ll be rewarded with some truly mind-enhancing moments.

And, if nothing else, you’ll be able to spout off random, newly-learned fun-facts at parties. Did you know that some animals sleep half of their brain at a time?

Restoring Rails session data when cookies aren’t available

Standard

C is for Cookie
If you’ve ever needed to implement user-friendly upload, you know intimately what a pain it is to get right. The web just isn’t built for uploading files from a browser. I mean, it kinda works, but even then only with a dozen or so limitations. Even the major photo and video sites have tried various solutions to make this easier for users. So when I built Dibs.net, I decided rather quickly to abandon all hope of getting it working flawlessly with plain ol’ Javascript and HTML, and instead looked into using a fairly nonintrusive Flash uploader component. (Without Flash installed, it just falls back to a simple HTML-based file-upload form.)

That’s not to say it was perfectly simple to get working with Rails. Because Dibs.net accepts uploads only from logged-in users, I ran into two limitations that would not allow me to use this solution:

  • Flash doesn’t send the cookies from the browser (at least it doesn’t in Firefox; it might in IE)
  • Rails doesn’t support non-cookie sessions

Because Flash doesn’t send the session cookie, Rails thinks the request is coming from a new, logged-out user and creates a new session for it. Adding a cookies feature to Flash was well out of my hands since I don’t work for Adobe, so I looked into a way to restore the session from a session key passed as a URL parameter. After some experimentation, I found a solution that works great.

Continue reading

De-tangling attr_reader, attr_writer and attr_accessor from attr_protected & attr_accessible (Part 1)

Standard

Car crashWhat a mess. You have undoubtedly run across these methods sprinkled throughout the Ruby and Rails world. If you’ve been working with Rails for even a short time, you’ve probably read a little about security and attr_accessible. But do you really understand what each of them do and when to use them?
I’m not a fan of whoever made these methods so closely named, especially because they serve very different purposes: two are specific to Rails (or more accurately, ActiveRecord), while the other three are Ruby core methods. When I have a need for any of them, I still have to really think about which one I actually want to use. Often I still have to glance at the rdocs to be reassured my choice is the right one. So let’s dive in and figure out what the heck these are supposed to do, and when to use them.

Continue reading

How to obtain the IP address of the current user

Standard

Some house address

Web applications can receive requests directly, via a CGI process, through proxy servers, relayed from front-end web servers, and so on. This can complicate how you might find out where the request originated if you, for example, wanted to limit an online poll to one vote per IP address. Luckily, Rails consolidates most of the ways to get this info into a single convenience method on the request object for us.

Continue reading

Microsoft adCenter vs Google Adwords (Round 1)

Standard

At the risk of being called a keyword Nazi and having to endure accusations that I care just a little too much about this stuff: Microsoft just managed surpass my experience with Yahoo.

As I mentioned, I’ve been advertising my online community classifieds site, Dibs.net, on Google for almost a month. Last night I decided to try out Microsoft’s advertising network for my community classifieds site. I copied some of my better performing ads from my Classifieds Ad Group on Google into my Classifieds Ad Group on Microsoft.

Here’s representative ad from the bunch:
Ad on Microsoft

I was in business fairly quickly — or so I thought. Microsoft has a similar “editorial guidelines” process to Yahoo’s. But at Microsoft, the process must go something like this:

  1. Take break from huffing paint fumes and watching Scooby-Doo
  2. Flip coin
  3. Heads, you get to advertise with your keyword; tails, you don’t

Microsoft rejected what I consider to the the most important keywords from my advertising, including “classifieds” and “community classifieds.”

I’ve given them a chance to respond before I start calling them names here ;)

(PS – Google’s success in advertising appears to be not without reason.)

Update: Microsoft took only a few hours to respond, and did so positively by reinstating the classifieds-related keywords. Good for them (and me). They blamed the problem on their automated editorial process, which raises the question: why would anyone automate such a thing? I think we can all agree computers are great at some things, but applying subjective and vaguely defined editorial guidelines isn’t one of them. Either way, I take back my paint fumes and Scooby-Doo comment above, since it appears they aren’t nuts after all.

Yahoo Marketing vs Google Adwords (Round 1)

Standard

Yahoo Ad
I’ve been advertising Dibs.net on both the Google and Yahoo ad networks for three weeks. I’ll have more to say later on, but I did want to share some notes about Yahoo’s “editorial process” regarding what search terms they let you advertise against. This process is allegedly for quality purposes, so that more relevant advertising is displayed to searchers.

Google has taken a more free-market approach to their editorializing of search terms you can advertise against. I’m sure they have a quality-control staff to keep ads clean, but they tend to let you spend your money however you want. I’m no Google fan, but I think Google’s approach is far superior, mainly because the market actually does self-correct mispositioned advertising: as people find their advertising for certain keywords isn’t working, they pare back the selection of keywords to be more laser-focused. I did this very thing; it works.

Yahoo, on the other hand, voluntarily protects certain company names (though who knows which ones) and is awfully serious about the relevancy of keywords you choose. But it’s all so inconsistent and confusing that you never know what they will allow. For example, they apparently allow some misspellings of brand names, but not others. And today I got notice they decided a term wasn’t relevant enough to Dibs.net — which surprised me, since I often describe Dibs.net using the exact term they rejected.

So, I just fired off an email to Yahoo support to see if they can make this situation clearer than the Mississippi mud they’ve given me till now.

Can you give me more detail as to why you believe the keyword “flea markets” isn’t applicable to my company, which is itself an online flea market (dibs.net)?

Removing the keyword from my campaign strikes me as an overly aggressive editorial decision, especially after conducting this search on Yahoo and noting NOT A SINGLE AD relates even remotely to flea markets. In fact, mine is the MOST RELEVANT of any company there. Of the most absurd listings you apparently allow, BizRate, Shopping.com, PalmersUniforms.com and Restaurant.com are advertised on the “flea markets” keyword.

Yes, Restaurant.com advertises under “flea markets” but dibs.net cannot? Come on, Yahoo! I’m trying to like your ad service. I really am. But this sort of random, haphazard enforcement of “editorial rules” leaves me plain confounded.

I have paused my advertising until I receive a response explaining how Yahoo can possibly hope to apply such picky rules consistently.

Thanks,
Kevin Hunt

We’ll see what they have to say about Restaurant.com’s flea market. Mmmmm, makes you hungry just thinking about it, doesn’t it?

Update (8/23): Yahoo responded this morning. They explained that because Dibs.net’s content is not about flea markets, the keyword is not allowed. Ok, fair enough, if those are the actual rules — but they’re not. That would be stupid. I responded and asked if Amazon would be allowed to advertise with the keywork “book stores,” since they have no information about actual book stores. Also, Yahoo’s response did not address how a site about restaurants can use the keyword they are disallowing for me. I’m still confused.

Come on, Yahoo! I really want to like you. Granted, this isn’t such a big deal in the grand scheme of things; but if I’m to commit an ad budget to you, you’d better clarify your rules and apply them consistently.