Let's say my controller looks like this:
class MyController < ApplicationController
  before_filter :find_user,:only => [:index,:create,:update,:destroy]
  def index
     @some_objects = @user.objects.all
  end
  ...
  private
  def find_user
    @user = User.find(params[:user_id])
  end
end
If the user_id param does not exist, @user will be nil.I think this is not the way:
def index
   if @user
      @some_objects = @user.objects.all
   else
      # ?
   end
end
The code would look uglier having all these checks in my controller ... not to mention I'd have to duplica开发者_运维问答te a lot of the logic if other controllers are similar to this one. How do you deal with these cases?
If the user_id param does not exist, then find method throw ActiveRecord::RecordNotFound exception. This exception is caught in a before_filter and rendered error. Аll subsequent filters and the index action will not be called.
class MyController < ApplicationController
  before_filter :find_user,:only => [:index,:create,:update,:destroy]
  def index
     @some_objects = @user.objects.all
  end
  private
  def find_user
    @user = User.find(params[:user_id])
  rescue ActiveRecord::RecordNotFound
    # render or redirect_to error
  end
end
The best way to make it perfectly dry is to use a dedicated gem: inherited_resources
It will basically handle everything for you, preloading as expected your resources according to the context.
Of course you can add your desired specific scopes, see tutorial.
I think it should be placed in the same filter:
private
def find_user
  @user = User.find_by_id(params[:user_id])
  redirect_to where_you_want_to_go_when_no_user_url unless @user #for example login page
end
If you want to render your controller actions even without a @user and you always need the @some_objects (and you don't want the variable to be null), you can have another before_filter:
def get_some_objects
  @some_objects = @user.present? ? @user.objects.all : []
end
or combining both options (redirect or set some_objects variable):
def set_variables
  @user = User.find_by_id(params[:user_id])
  if @user
    @some_objects = @user.objects.all
  else
    redirect_to where_you_want_to_go_when_no_user_url
  end
end
I hope this helps.
EDIT: change 'find' to 'find_by_id' to avoid errors, when id is null or user for given id does not exist.
When you ask for a specific id and AR can't find it, it throws a RecordNotFound error. You would have to catch that with something like:
irb(main):025:0> begin
irb(main):026:1* Location.find 100
irb(main):027:1> rescue ActiveRecord::RecordNotFound => e
irb(main):028:1> puts "Oops: #{e.message}"
irb(main):029:1> end
Oops: Couldn't find Location with ID=100
=> nil
If you are wanting to apply something to all controllers you should probably think about adding your method to ApplicationController...
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
 加载中,请稍侯......
      
精彩评论