views:

43

answers:

1

In my controller i have an action which does not have a corresponding view. Precisely: the upload action for uploading images. However, i require the current users id to store the image url. But the current_user method always returns nil, as the action by itself does not have a view. In such scenarios how do i fetch the current_user? I am using authlogic. My application_controller.rb contains the following:

class ApplicationController < ActionController::Base

  helper :all
  helper_method :current_user_session, :current_user
  filter_parameter_logging :password, :password_confirmation
  protect_from_forgery

  def correct_safari_and_ie_accept_headers
    ajax_request_types = [ 'application/json', 'text/javascript', 'text/xml']
    request.accepts.sort!{ |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 } if request.xhr?
  end

  private
    def set_cache_buster
       response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
       response.headers["Pragma"] = "no-cache"
       response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
    end

    def current_user_session
      return @current_user_session if defined?(@current_user_session)
      @current_user_session = UserSession.find
    end

    def current_user
      return @current_user if defined?(@current_user)
      @current_user = current_user_session && current_user_session.record
    end
end

EDIT: All other actions in the controller are able to access the current_user helper method. Only the upload action is not able to. Code:

Controller:

class ImageStacksController < ApplicationController
 def upload
    # Using swfupload.

    image_stack_params = { 
      :caption => params[:caption], 
      :swf_uploaded_data => params[:link]
      }

    # current_user returns nil, even with user logged in!!
    # Occurs only in the upload action and no other action in this controller.
    logger.info("Current User: #{current_user}") #Returns nil
    @image_stack = current_user.image_stacks.create! image_stack_params


      respond_to do |format|
        format.js { render :json => @image_stack }
      end
  end

  def edit
   logger.info("Current User: #{current_user}") #Returns current user
  end

  def new
   logger.info("Current User: #{current_user}") #Returns current user
  end

  def update
   logger.info("Current User: #{current_user}") #Returns current user
  end

  def destroy
   logger.info("Current User: #{current_user}") #Returns current user
  end
 end

Model:

class ImageStack < ActiveRecord::Base
  belongs_to :user, :class_name => "User", :foreign_key => "user_id"

  upload_image_to_s3 :link

  def swf_uploaded_data=(data)
      data.content_type = MIME::Types.type_for(data.original_filename)
      self.link = data
  end  
end
+1  A: 

The controller method is really just that, a class method. It does not require a view. My making it a private method the method is not available outside the class or other classes inheriting from it and as such it is correctly not available to the view. Your problem suggests that your user is not logged in or something else is wrong. Do you have a require_user method?

#application_controller
private

def require_user
  unless current_user
    store_location
    flash[:notice] = t(:must_be_logged_in)
    redirect_to user_login_path
    return false
  end
end

def store_location
  session[:return_to] = request.request_uri
end

#user.rb
has_many :images

#image.rb
belongs_to :user    

# image_controller.rb
before_filter :require_user

def create
  @photo = @item.images.new(:photo => params[:photo],  :user => current_user)

Edit:

Your current_user method is a ApplicationController method which is already inherited:

ImageStacksController < ApplicationController

This:

helper_method :current_user_session, :current_user

is providing the methods to the view.

The difference between the upload action and all the others is update is being called by javascript. I remember doing a similar uploader and having to pass the authenticity token. Is anything else being reported in the log?

This might be of use to you: http://github.com/JimNeath/swfupload---paperclip-example-app

Making the authenticity token available to js goes something like this:

- content_for :head do
  = javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery?

Now you add the field to swflupload the same way you added current_user.

mark
I am making it available to other classes inheriting from it by using the helper method `:current_user`. The `upload` action is the only action that is not able to access the `current_user` method. Other actions in the same controller are able to access it though! Really, really weird!! I will update my question with the `upload` action code.
Shripad K
See edit section above :)
mark
@mark: There is nothing else reported in the log, other than the fact that current_user is nil! So, if the helper methods are for the views all i will have to do is pass the current_user as a param using swfupload!! Yup, i got it now. Thanks :)
Shripad K
Although that might work it isn't secure - a user could create an image masquerading as another user. I really think you need to look into passing the authenticity token with swfupload and require_user in your image controller. Have added small edit above.
mark
@mark. The funny thing is it does not play nicely with authentication. I am using authlogic to authenticate users. The session information is just not available to the `upload` action!! I tried many tutorials but to no avail. Any input on this?
Shripad K