Tuesday, February 17, 2009

View helpers in flash

The other day I wanted a nice checkout link in my flash when users added a product to their cart (apart from the checkout in cart area). I soon realized (or remembered) that you don't have access to view helpers in the controller, where you usually assign flash messages.

I spent about 2 hours researching on how to do this but got no answer. People resorted to fancy stuff just to put links in their flash messages. I thought the answer was in the render method. I first tried to use it but it didn't work because you can't call render/redirect_to twice in the same action:

flash[:notice] = render :partial => "some/partial"

So I looked at the source and tried to figure out what it was in render that read the file and spat out the text. 10 minutes later, I got this to work:

flash[:notice] = @template.render(:partial => "some/partial")

So now I can use link_to and other nice view helpers in that partial and it will all render nicely in the flash message. :)

Thursday, February 12, 2009

Smart Activation With Single Sign On

This post is related to another post of mine about getting the rpx single sign on to work.

  • You are using single sign on but require the user to have emails (Facebook does not return email) or require other fields (eg. accept terms of use).
  • You allow users to specify another email besides the one that is returned by the single sign on service (SSOS)
  • If the user changes that email, you want them to validate it (you send an email to them with a link to activate their account), but if they don't change it (meaning they use the same email that is returned by the SSOS), then the account will be automatically activated
For some reason, I did this the hard way at the beginning. I won't expound on how but what I tried to do in 2 days (but failed) actually took 30 minutes doing it the right way (and worked).

  1. Make sure you got single sign on working (you're able to read responses and stuff)
If you look at my code and read it a few times you'll understand what I do. From the RPX Controller, you render the login form so they have a chance to change stuff. If they miss out on anything the errors will render. If they submit it, then the form will be submitted to users/create and will render itself if they are still missing stuff. The hidden_field of email_was just stays there, dormant, waiting to be compared later on.

When the user finally has all their stuff filled up and submits the form, if they're on single sign on, then the user will be activated based on the comparison between the email_was and the current email they're trying to save. If they're different, then they're not activated and the user observer sends out the activation mail. If they are the same email, then the account is activated and they have to do one less step. :)

If you have any comments or suggestions please let me know.

Sunday, February 8, 2009

Blocks in View

I had a bunch of "if logged_in? && current_user.admin?" in my views, which made it very ugly. I saw an old video (it is also covered again) from Railscasts and knew this would be my answer.

However, I wanted more customization though. What if I didn't want to wrap my admin_area in a div? What if I wanted to add conditions on the fly and not make a zillion [enter_some_name]_area methods?

This would be particularly useful if, for example, I only want the "delete" option of an object to appear to admins and if the object if destroyable.

In haml:

- admin_area(:conditions => @object.destroyable?) do
= link_to "Destroy", ...

Take a look at my helper method to see what I did. I'd appreciate any comments!

Saturday, February 7, 2009

Form Builder

I don't know why I never know about Form Builder! I was making my own form helpers but in the completely stupid way - in the helper files, which made it clunky. Check out these two posts that helped me out a lot. Although it can seem complicated because of all the (what I think is) meta programming, I suggest you just dive in and explore.

Friday, February 6, 2009

RPX Now: Single Sign-on

As I write this, I'm trying to install the single sign-on capability that RPX Now gives you on my Rails app. I've tried OpenID before (using open_id_authentication plugin and ruby-openid gem) and it was mightly complicated, plus you couldn't only use other 3rd party accounts.

RPX Now claims to be super easy and so far, with grosser's rpx_now gem, it almost seems too easy -- except there are no tutorials that I can find on Google. There are examples in gem's github site but they don't explain much.

This is my attempt at writing one.

First, install the gem (instructions in the github site). If you want to put it in your environment.rb file, it should look like this (remove or replace the version number with an updated one):
config.gem "grosser-rpx_now", :lib => "rpx_now", :version => "0.3", :source => "http://gems.github.com"
Then create an RpxController and add code similar to this to your user model. Of course, you don't have to process the data yourself, but I wanted to (thus my rpx_controller is a bit longer, and I had to read the response in the User model) so that if the rpx profile is missing anything, it will render a something like my normal login page that basically has a form_for(@user ...) where they can fill up the missing data.

Check out actual responses (I just removed any personal data).

Hosting Services

I don't run websites with thousands of users at a time, however, I thought I'd still announce what I use for my hosting services.

VPS: SilverRack
Good price, quick service. They don't spend time fussing over you though, but that's expected in a VPS.

Shared: HostingRails (disclaimer: affiliate link)
I've tried BlueHost, Dreamhost, but I've found HostingRails to be the easiest to deal with. Their support replies lightning fast, and don't diss you even if your problems are your fault!

Tuesday, February 3, 2009

Using --trace; cucumber & machinist order of loading files

I followed this tutorial to easily use Cucumber with a fixture replacement plugin called Machinist. It worked great on my desktop, but when I moved to my laptop, running rake features didn't work - an "uninitialized constant Sham" error popped up and I spent a day figuring it out.

Although the context of this problem is Cucumber and Machinist (which includes Sham), this is a post that talks about using --trace when you run into problems similar to this.

The problem occured partially because I put my blueprints.rb file where env.rb is. I believe cucumber loads everything there in alphabetical order (doesn't explain why my desktop loaded things differently). The problem is that blueprints.rb tries to call "Sham" which is something that is loaded by Machinist, which in turn is loaded during or after env.rb, not before.

The problem occured because of the order files were loaded. I do not know why files were loaded differently in my desktop vs the laptop, but what the heck -- I found the error by using --trace and actually read the big bad ugly code that rake conveniently hides from us.


So the lesson is: actually read what --trace spits out! :)