Tag Archives: rails

IE + iframe + cookies

After spending lots of hours building a system for a client, using Ruby on Rails, everything was deployed and worked perfect… until IE came along that is.

The customer had iframed the project into their current website, and since the user had to sign in to the new project using an iframe, IE began to give all kinds of errors.
The direct link worked like a charm, but IE seems to want more!

I stumpled upon an answer on stackoverflow – where else? (link to stackoverflow answer)
It simply states, that if you want to use cookies in iframes, using IE, you need to add a P3P header.
And it worked!

Rails howto

To do this in Rails, simply open up “application_controller.rb” and add a new filter:
before_filter :set_pthreep

The code for the filter is added in the private section of the application_controller.rb file:
def set_pthreep
response.headers['P3P']= 'CP="Potato"'
end

And that’s all there is to it.

Using rails and respond_to to include nested data

I want to display data from a nested table in my XML output using respond_to. I searched google a bit and it seems :include was the way to go. However I had some problems getting this to work properly.

I have two models (customer and user) that are linked together. When I fetch the data for a single user, I want my xml output to include the customer data.

The Customer model:

class Customer < ActiveRecord::Base
  has_many :users
end

The User model:

class User < ActiveRecord::Base
  belongs_to :customer
end

In my UserController I use the respond_to method to respond to html and xml data.
The show action is as follows:

# Shows the seleted user
def show
  @user = User.find(params[:id])
  
  respond_to do |format|
    format.html
    format.xml { render :xml => @user) }
  end
end

Calling the show action on the user controller as xml should yield something like:

<user>
  ...
  <customer>
    ...
  </customer>
</user>

But the customer data is not included.
This puzzled me a bit.

Searching a bit on google got me the following answer:

# Shows the seleted user
def show
  @user = User.find(params[:id])
  
  respond_to do |format|
    format.html
    format.xml { render :xml => @user.to_xml(:include => @user.customer) }
  end
end

source: http://rubydoc.info/docs/rails/3.0.0/ActionController/MimeResponds

(I also tried fetching the customer out separately, that didn't work either)

This gave me the following error:

undefined method `macro' for nil:NilClass

The solution

After a lot more searching I found out, that you shouldn't pass an object, but a symbol. The name of the symbol is the data block you want to show, so in my case it was :customer

The code to fix it was:

# Shows the seleted user
def show
  @user = User.find(params[:id])
  
  respond_to do |format|
    format.html
    format.xml { render :xml => @user.to_xml(:include => :customer) }
  end
end

The data for the customer now returned as well.

Need more data?

If you need data from several tables, just use an array of symbols instead.

# Shows the seleted user
def show
  @user = User.find(params[:id])
  
  respond_to do |format|
    format.html
    format.xml { render :xml => @user.to_xml(:include => [:customer, :table2, :table3]) }
  end
end

Hope you can use this tip.

Rails plugin development using WebMock

I had a few problems getting WebMock working with my rails 3 setup.

When I used webmock in my rails 3 app, the tests ran and all was nice.
But when I wanted to create a plugin using the exact same code as I just tested inside my rails app, I went into some problems.

To start, I created a new plugin using

rails generate plugin myclient

The files were generated and all seemed fine.
I then wanted to use the webmock plugin, since my client relied on some external services. (Which a test really shouldn’t do)

I had a really simple test case, just to get started:

require 'test_helper'
require 'webmock/test_unit'
require 'curb'

class MyClientTest < ActiveSupport::TestCase
  # Replace this with your real tests.
  test "the truth" do
    assert true
  end
  
  test 'webmock testing' do
    WebMock.stub_request(:any, 'www.example.com').to_return(:body => 'tester')
    data = Curl::Easy.perform("www.example.com")
    p data.body_str
    assert data.body_str == 'tester'
  end
end

When I ran “rake test” the test failed and the body that was returned, was the body of the actual page at www.example.com.
After bashing at the problem for a long time, I found out, that webmock doesn’t work if webmock is required before curb.

So… This was just a note about something that really took up too much of my time, and… yes, I should have know that webmock couldn’t “overwrite” the curb methods, if it was loaded in first.

Anyways, the final code that works!

require 'test_helper'
require 'curb'
require 'webmock/test_unit'

class MyClientTest < ActiveSupport::TestCase
  # Replace this with your real tests.
  test "the truth" do
    assert true
  end
  
  test 'webmock testing' do
    WebMock.stub_request(:any, 'www.example.com').to_return(:body => 'tester')
    data = Curl::Easy.perform("www.example.com")
    p data.body_str
    assert data.body_str == 'tester'
  end
end

Using form_tag and collection_select with Rails3

After being away from rails for a while, i’m coming back en version 3 to check it all out again.

I had a problem with how to create a simple select, using the FormHelper.

I had two models, a user and a customer. They are defined as follows:

class User < ActiveRecord::Base
  belongs_to :customer
end
class Customer < ActiveRecord::Base
  has_many :users
end

In my UserController I have an action called new, where I initialize a new user object and fetch all the customers from the database:

class UsersController < ApplicationController
  # Opens the new user view.
  def new 
    @user = User.new
    # fetches all the customers, ordered by their name
    @customers = Customer.order(:name)
  end
end

However, when I wanted to associate the new user and a customer I couldn't remember how this was done. Then I headed over to api.rubyonrails.com and found the FormHelper, which didn't help me much though...
Then I looked at the FormOptionsHelper, which has the method:
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})

In order to use this in my view, I had the following code:

<% form_for @user do |f| %>
<ul>
  <li>
    <%= f.label :customer %>
    <!-- select element here!-->
  </li>
  <li>
    <%= f.label :name %>:
    <%= f.text_field :name %>
  </li>
  <li>
    <%= f.label :email %>:
    <%= f.text_field :email %>
  </li>
  <li>
    <%= f.submit %>
  </li>
</ul>
<% end %>

The method states that it needs an object, a method, a collection, value, text. This resulted in the first try:

<li>
  <%= f.label :customer %>
  <% f.collection_select :user, :customer_id, @customers, :id, :name %>
</li>

Which gave a nice error...

This worked however:

<li>
  <%= f.label :customer %>
  <%= f.collection_select :customer_id, @customers, :id, :name %>
</li>

Why?
Well the form_tag was being done on the user object already, so the first object could be skipped.

Hope you can use it!

Using link_to in rails with :confirm and :method

Every time i’m going to use the link_to method in rails, I always seem to get a lot of errors.

The documentation states:

link_to(name, options = {}, html_options = nil)
link_to(options = {}, html_options = nil) do
# name
end

URL to the rails docs: http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#M001597

And gives a list of options you can set. However, I always seem to have problems remembering the correct syntax if I want to use :confirm and :method.

After fiddling with it a bit, I found that the proper way of using is:

%lt%= link_to(
  t("Delete"), 
  {
    :action => "destroy",
    :id => some_id
  },
  :method => :delete,
  :confirm => t('Are you sure you want to delete it?')
) %>

My biggest problem was, that you do not need to add the controller.

Also, found a nice write up about this on Ryan’s Scraps blog (a bit old post, but still…)

Hope you can use the tip.

Use Rails’ form_tag with care

Today at work I was fiddling with some forms in an admin interface. When I had to make an update form, the data didn’t hit the correct controller action.

If you ever get the message ActionController::MethodNotAllowed, then you’ve created your form wrong!

The error came when I tried doing:

<% form_tag :action => :update, :method => :put do %>
  lots of fields here
<% end %>

The data was not sent correctly (it was sent as POST, not as PUT as I wanted) and the action was not found. After googling for a bit, I found out that others had a similar problem.

The answer was rather simple though. In the rails docs you use the form_tag like this:

form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block)

What I didn’t realize straight away was, that my :method => put was being sent in the first hash and NOT the second as it was suppose to.
So if you are creating your own forms, without activerecord, do it like this:

<% form_tag({:action => :update}, {:method => :put}) do %>
  lots of fields here
<% end %>