views:

526

answers:

3

So my background is in Java web services, but I'm trying to make the move to ROR.

I'm using FlexImage to handle image uploading and thumbnail generation. I followed the guide and CRUD behavior was working fine at one point. However, at some point, CRUD behavior for one of my models (Images) was broken.

The error code I'm getting back is as follows: ActiveRecord::RecordNotFound in ImagesController#show -- Couldn't find Image with ID=#<Image:0x4e2bd74>. In other words, when I'm telling Rails to create/update/destroy, it is confusing the object with the id. This seems to indicate there might be a routing issue. I thought adding a partial for images might have been the trouble, but rolling back the changes didn't fix it.

Following are the new, show and update methods of the controller for the Images model:

      # images_controller.rb

        # ...

      def new
        @image = Image.new

        respond_to do |format|
          format.html # new.html.erb
          format.xml  { render :xml => @image }
        end
      end

    # ...
  def show
    @image = Image.find(params[:id])

    respond_to do |format|
      format.jpg  # show.jpg.erb 
      format.html # show.html.erb
      format.xml  { render :xml => @image }
    end
  end



    # ...

      def create
        @image = Image.new(params[:image])

        if @image.save 
        redirect_to image_url(@image)
        else
        flash[:notice] = 'Your image did not pass validation.'
        render :action => 'new'
        end
      end 
     # ...

Note that show() is, of course, expecting an appropriate id. Here's the new.html.erb for uploading a new image:

# new.html.erb [upload image]
<h1>New image</h1>

<% form_for @image, :html => { :multipart => true } do |f| %>
  <%= f.error_messages %>
  <table><tr><td width="50%">
  <p>
    <%= f.label :filename %><br />
    <%= f.text_field :filename %></p>
  </td>
  <td><p><b>Upload Image</b><br />
    <%= f.file_field :image_file %><br />
    or URL: <%= f.text_field :image_file_url %>
    <%= f.hidden_field :image_file_temp %>
  </td>
  <td>
    <b>Uploaded Image:</b><br />
    <%= embedded_image_tag(@image.operate { |img| img.resize 100 }) if @image.has_image? %>
  </td>
  </tr>

  </table>
  <p>
    <%= f.label :description %><br />
    <%= f.text_area :description %>
  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

<%= link_to 'Back', images_path %>

The relevant portion of routes.rb are as follows:

# routes.rb [excerpt]

  map.resources :images
  map.image 'images/:action/:id.:format', :controller => 'images'

Also note that a new image does actually get uploaded and the error is thrown on redirect to show (which is expecting a valid ID in params[:id] and not the object which for whatever reason it is being handed.)

Thanks for your help in advance, and please let me know if anything jumps out at you.

+1  A: 

My suggestion is to use ruby-debug and set a break point right before the Image.find call. Inspect params[:id] and see what it actually is.

A more ghetto approach, put this before the Image.find call

logger.info params[:id].class

and see what is in that variable. Is it possible that you have some sort of before filter that is manipulating it?

jshen
Thanks! That's exactly what seems to be going on. The class of params[:id] is a String, and it's value is equal to the object handle, i.e., "#<Image:xxxxx>". What could be making the id transform like this? The only instruction below the ImagesController class definition is a "cache_pages :show".
Joe
Do a view source in your browser and see what is in the form. That's my first guess.
jshen
+5  A: 

From looking at the code it appears to me that the problem may be caused by using image_url(@image) in combination with the non-RESTful image route.

You will probably want to remove the line

map.image 'images/:action/:id.:format', :controller => 'images'

from your routes.rb.

The line

map.resources :images

should actually be enough to expose all CRUD actions in your ImagesController.

molf
I was wondering about this. Thanks for the help!
Joe
A: 

try

  redirect_to :action => "show", :id => @image

I think that's a more idiomatic way to code the redirect. And +1 to molf's advice about RESTful routes.

asplake
At least you'll have to include the id in that case:redirect_to :action => "show", :id => @images.id
molf
Actually it works without, and it gives Rails the chance to use #to_param if one is defined on the model.
asplake
You're right, I was (apparently prematurely) referring to your pre-edit version. Never mind now ;)
molf