views:

26

answers:

1

I'm making a web app where the point is to change a given word by one letter. For example, if I make a post by selecting the word: "best," then the first reply could be "rest," while the one after that should be "rent," "sent", etc. So, the word a user enters must have changed by one letter from the last submitted word. It would be constantly evolving.

Right now you can make a game and respond just by typing a word. I coded up a custom validation using functionality from the Amatch gem:

http://flori.github.com/amatch/doc/index.html

Posts have many responses, and responses belong to a post.

here's the code:

   def must_have_changed_by_one_letter
        m = Amatch::Sellers.new(title.strip)
        errors.add_to_base("Sorry, you must change the last submitted word by one letter")   
        if m.match(post.responses.last.to_s.strip) != 1.0
   end

When I try entering a new response for a test post I made (original word "best", first response is "rest") I get this:

ActiveRecord::RecordInvalid in ResponsesController#create Validation failed: Sorry, you must change the last submitted word by one letter

Any thoughts on what might be wrong? Thanks!

+1  A: 

Looks like there are a couple of potential issues here.

For one, is your if statement actually on a separate line than your errors.add_to_base... statement? If so, your syntax is wrong; the if statement needs to be in the same line as the statement it's modifying. Even if it is actually on the correct line, I would recommend against using a trailing if statement on such a long line; it will make it hard to find the conditional.

if m.match(post.responses.last.to_s.strip) != 1.0
    errors.add_to_base("Sorry, you must change the last submitted word by one letter")
end

Second, doing exact equality comparison on floating point numbers is almost never a good idea. Because floating point numbers involve approximations, you will sometimes get results that are very close, but not quite exactly equal, to a given number that you are comparing against. It looks like the Amatch library has several different classes for comparing strings; the Sellers class allows you to set different weights for different kinds of edits, but given your problem description, I don't think you need that. I would try using the Levenshtein or Hamming distance instead, depending on your exact needs.

Finally, if neither of those suggestions work, try writing out to a log or in the response the exact values of title.strip and post.responses.last.to_s.strip, to make sure you are actually comparing the values that you think you're comparing. I don't know the rest of your code, so I can't tell you whether those are correct or not, but if you print them out somewhere, you should be easily able to check them yourself.

Brian Campbell
Thanks Brian, that helped. I believe I put the if statement on the same line, but I suppose it got clobbered when I hit submit.The Hamming distance does seem to be a better match. Thanks for those recommendations. In the console:post = Post.find_by_id(1)post.responses.last.to_s=>"#<Response:0x103275db8>"So that's where the problem lay. It wasn't comparing the actual last response text, but the object ID. So I removed the to_s and replaced it with the title attribute of Response:post.responses.last.titleI think that did the trick. Thanks for leading me in the right direction!
dartfrog