How to control respond_to based on variable in Rails controller?
The dilemma
I'm using a before_filter
in my controller that restricts access to admins. However, I want to allow access public access to some methods based on request format
. See the index
method to understand what I'm talking about.
application_controller.rb
class ApplicationController < ActionController::Base
# ...
def current_user
@current_user ||= User.find_by_id(session[:user])
end
def superuser_required
redirect_to login_path unless current_user.superuser?
end
end
items_controller.rb
class ItemsController < ApplicationController
before_filter :sup开发者_JS百科eruser_required
layout 'superuser'
def index
@items = Item.all
respond_to do |format|
format.html
format.js # I want public to have access to this
end
end
def show
@item = Item.find(params[:id])
respond_to do |format|
format.html
end
end
def new
@item = Item.new
respond_to do |format|
format.html
end
end
# remaining controller methods
# ...
end
Filters have access to the request
object which has a format
method you can use to obtain the request format. Change your before filter so that if the format is JavaScript then the request processing is allowed to proceed. Something like:
def superuser_required
return true if request.format == Mime::JS
redirect_to login_path unless current_user.superuser?
end
Way easier than I expected
2 days later
class FoosController < ActiveRecord::Base
# use :except to open `show` action for public js access
before_filter :superuser_required, :except => 'index'
# before_filter does not apply here
def index
@foos = Foo.all
respond_to do |format|
# restrict behavior on html access for superusers
format.html do
superuser_required # functions same as before_filter
end
# unrestricted on js access for public but only shows foo.id and foo.name
format.js do
render :text => @foo.to_json(:only => [:id, :name])
end
end
end
# restricted to superuser per before_filter
def new
@foo = Foo.new
respond_to do |format|
format.html
end
end
# restricted to superuser per before_filter
def show
@foo = Foo.find(params[:id])
respond_to do |format|
format.html
end
end
end
Either I totally missed something when I was learning about respond_to
or my original question was completely incoherent. I just read it again, though, and it still seems like this only (and most) appropriate way to address my issue.
Surprisingly, I couldn't really find any examples of this kind of behavior on the web either. Oh well. Now I know more about respond_to
, right?
精彩评论