---
title: Using @url Instance Variable in Rails
teaser:
tags: web,rails
author: Matt Jankowski
published_on: 2008-01-25
---

I was going into a project to do some general code refactoring (it's a hobby you
know), and found some tests that were failing.  Figured I'd fix those first and
then whine to whoever left failing tests in a project later. One test failure in
particular looked a bit odd to me:

<pre>
<samp>1) Error:
test: The 'Add to Web' form should pass a URL into the form. (LettucesControllerTest):
ActionView::TemplateError: undefined method &#96;rewrite' for "http://mocked.com":String
    On line #1 of layouts/\_footer.html.erb

        1: <%= link_to 'Privacy Policy', privacy_policy_path %>
        2: <%= link_to 'Terms & Conditions', terms_path %>
        3: <%= link_to 'Contact Us', site_contact_path %>

        (eval):15
        app/views/layouts/\_footer.html.erb:1</samp>
</pre>

...that's interesting, I thought. What does `http://mocked.com` have to do with
anything in that line?  Well the functional test looked like this:

```ruby
setup do
  login_as :activated_user
  get :new, :url => 'http://mocked.com'
end
```

...and the action in the controller looked like this:

```ruby
# User added lettuces page
# scrapes lettuce URL if given for suggested title and images
def new
  @url = params[:url]
  @lettuce = @url.blank? ? Lettuce.new : Lettuce.from_url(@url)
end
```

![''](http://images.thoughtbot.com/ui/2008-1-25-lettuce.jpg "¡Lechuga!")

Ok, it looks like an external site can pass a `url` param in via the url, to
indicate which page this action should reach out to and scrape for `Lettuce`
content.  I removed the `@url` assignment line from the action and put a `<%=h
@url.class %>` and and `<%=h @url.methods.sort %>` into the `new` view file and
loaded that in my browser.

Sure enough, `@url` is an `ActionController::UrlRewriter`, and it has a
`#rewrite` method, amongst some other things. I'm guessing that Rails routing is
using this somewhere, but I'm not curious to go find out because it will delay
my refactoring mission.

Now, thankfully I didn't like that there was an instance variable named `@url`
in the first place, since it was being created only for the purpose of letting
the view use an instance variable instead of accessing `#params` directly.
However, there was a conditional case in the view for how to handle a `#blank?`
url vs a non blank url, so it had to be available to the view somehow. I
refactored to:

```ruby
def new
  @lettuce = requested_lettuce_url.blank? ? Lettuce.new : Lettuce.from_url(requested_lettuce_url)
end

protected

helper_method :requested_lettuce_url
def requested_lettuce_url
  params[:url] || ''
end
```

And now:

- The functional tests all pass.
- `@url` does not get overwritten, so the routing code will now work.
- The view has access to a `#requested_lettuce_url` method (a bit verbose, but
  `#lettuce_url` collides with a named route).
- The incoming param stays the same, so any external pages which linked to this
  `import lettuce` view won't have to change how they link to the page.

Now that the `lettuces_controller` is looking good, I can start working on the
`meats_controller` and see what it has in store.
