Is there a way to disable all cookies for a Rails app? Or preferably on a controller by controller basis? My problem is regarding access of a Rails JSON api by an Adobe Lightroom plugin. Apparently the presence of any cookie data in the response from the server causes an error in Lightroom.
In the controller you want to avoid cookies, add this:
after_filter :skip_set_cookies_header
def skip_set_cookies_header
request.session_options = {}
end
If you have a set of api controllers, set this in a api_controller class and let your other controllers inherit the api_controller.
This skips setting Set-Cookie header since the session opts is empty.
If you're using Apache, you can turn probably turn off cookies in the response by using mod_headers, which is a standard apache mod.
Header always unset "Set-Cookie"
You might want to use ActionController::Metal and add any additional modules that you might need.
ActionController::Metal is pretty barebone and skips most of the functionality of a typical ApplicationController including cookies.
You can call ApplicationController.ancestors to get an idea of what is typically included in contrast with ActionController::Metal.ancestors
Here's how I would most likely set it up.
class SimpleController < ActionController::Metal
#include ...
#include ...
end
class FirstApiController < SimpleController
def index
#Code
end
end
class SecondApiController < SimpleController
def index
#Code
end
end
Related
I'm using Intercom rails in my application and I would like to not include intercom script in a certain situation. So, I would like to skip the intercom after_filter when a value is set in the user session.
I tried that, but it didn't worked:
class ApplicationController < ActionController::Base
before_filter :verify_session
def verify_session
if skip_intercom?
self.class.skip_after_filter :intercom_rails_auto_include
end
end
end
Any idea if it's possible?
#Rafael Caricio i faced the same issue but later i have added the below filter in all of my controllers where i don't want intercom to add:
skip_after_filter :intercom_rails_auto_include
and it is working fine for me
Where is the intercom_rails_auto_include being set? Because Could you not just put skip_after_filter_intercom_rails_auto_include at the top your of your application controller. Or alternatively try and do the following skip_after_filter IntercomRails::AutoIncludeFilter at the top of your controller.
This is going to sound strange, but hear me out...I need to be able to make the equivalent of a POST request to one of my other controllers. The SimpleController is basically a simplified version of a more verbose controller. How can I do this appropriately?
class VerboseController < ApplicationController
def create
# lots of required params
end
end
class SimpleController < ApplicationController
def create
# prepare the params required for VerboseController.create
# now call the VerboseController.create with the new params
end
end
Maybe I am over-thinking this, but I don't know how to do this.
Inter-controller communication in a Rails app (or any web app following the same model-adapter-view pattern for that matter) is something you should actively avoid. When you are tempted to do so consider it a sign that you are fighting the patterns and framework your app is built on and that you are relying on logic has been implemented at the wrong layer of your application.
As #ismaelga suggested in a comment; both controllers should invoke some common component to handle this shared behavior and keep your controllers "skinny". In Rails that's often a method on a model object, especially for the sort of creation behavior you seem to be worried about in this case.
You shouldn't be doing this. Are you creating a model? Then having two class methods on the model would be much better. It also separates the code much better. Then you can use the methods not only in controllers but also background jobs (etc.) in the future.
For example if you're creating a Person:
class VerboseController < ApplicationController
def create
Person.verbose_create(params)
end
end
class SimpleController < ApplicationController
def create
Person.simple_create(params)
end
end
Then in the Person-model you could go like this:
class Person
def self.verbose_create(options)
# ... do the creating stuff here
end
def self.simple_create(options)
# Prepare the options as you were trying to do in the controller...
prepared_options = options.merge(some: "option")
# ... and pass them to the verbose_create method
verbose_create(prepared_options)
end
end
I hope this can help a little. :-)
My application is a form builder: forms are defined, and activated ones are then presented in the usual CRUD manner. The process of activating a form triggers the FormManager to create a subclass of the main Form object (I use STI in ActiveRecord to create a subclass of type, using Object.const_set()). Active forms can be deactivated, which involves killing that subclass definition (using Object.const_send(:remove...))
I require only 1 FormManager object for my application. What is the best way to go about this? I am currently using a class variable in ApplicationController to achieve this... it works, but seems a bit clunky:
require 'lib/form_manager.rb'
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
attr_reader :registry
protect_from_forgery
##registry = FormManager.new
end
I'm running ruby 1.8.7, rails 2.3.11 in development mode - am I seeing this just because I'm in development mode?
No, it just works that way. Rails has request-response model, and for every request it creates new instance of some controller (which probably inherits from your ApplicationController), sets some request params and then fires your action method. If you want to share state between requests, you need to put it outside of controller, for example as constant (it's just Ruby) initialized while your application is started by server.
If you need single instance of registry, just put it in "config/initializers/registry.rb":
require 'lib/form_manager.rb'
REGISTRY = FormManager.new
Template.all(:conditions => { :is_active => false }).each do |t|
REGISTRY.loadForm(t.id)
end
and then in ApplicationController:
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery
def registry
REGISTRY
end
end
You might want to make your FormManager a singleton:
http://dalibornasevic.com/posts/9-ruby-singleton-pattern-again
Yes, a new ApplicationController object will be created for every request (you can check this by adding a before_filter that runs "puts self.id" to check the object id for your controller object. You'll notice it's different for every request).
Why would you want a single object across requests? what are you trying to achieve?
I am in the middle of migrating my application from using subdirectories for userspace to subdomains (ie. domain.com/~user to user.domain.com). I've got a method in my user class currently to get the "home" URL for each user:
class User
def home_url
"~#{self.username}"
# How I'd like to do it for subdomains:
#"http://#{self.username}.#{SubdomainFu.host_without_subdomain(request.host)}"
end
end
I'd like to update this for subdomains, but without hardcoding the domain into the method. As you can see, I am using the subdomain-fu plugin, which provides some methods that I could use to do this, except that they need access to request, which is not available to the model.
I know it's considered bad form to make request available in a model, so I'd like to avoid doing that, but I'm not sure if there's a good way to do this. I could pass the domain along every time the model is initialized, I guess, but I don't think this is a good solution, because I'd have to remember to do so every time a class is initialized, which happens often.
The model shouldn't know about the request, you're right. I would do something like this:
# app/models/user.rb
class User
def home_url(domain)
"http://#{username}.#{domain}"
end
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# ...
def domain
SubdomainFu.host_without_subdomain(request.host)
end
# Make domain available to all views too
helper_method :domain
end
# where you need it (controller or view)
user.home_url(domain)
If there is such a thing as a canonical user home URL, I would make a configurable default domain (e.g. YourApp.domain) that you can use if you call User#home_url without arguments. This allows you to construct a home URL in places where, conceptually, the "current domain" does not exist.
While molf's answer is good, it did not solve my specific problem as there were some instances where other models needed to call User#home_url, and so there would be a lot of methods I'd have to update in order to pass along the domain.
Instead, I took inspiration from his last paragraph and added a base_domain variable to my app's config class, which is the set in a before_filter in ApplicationController:
module App
class << self
attr_accessor :base_domain
end
end
class ApplicationController < ActionController::Base
before_filter :set_base_domain
def set_base_domain
App.base_domain = SubdomainFu.host_without_subdomain(request.host)
end
end
And thus, when I need to get the domain in a model, I can just use App.base_domain.
Our application is developed using Rails 2.3.5 along with ActiveScaffold. ActiveScaffold adds quite a bit of magic at run time just by declaring as following in a controller:
class SomeController < ApplicationController
active_scaffold :model
end
Just by adding that one line in the controller, all the restful actions and their corresponding views are made available due to ActiveScaffold's meta programming. As most of the code is added at runtime, in development mode requests seems to be little slower as there is no class_caching.
We needed to add a authorization layer and my team has chosen Lockdown plugin which parses an init.rb file where you declare all the authorization rules. The way that Lockdown stores the authorization rules is by parsing the init.rb file and evaluating the controllers declared in the init.rb file. So for every request Lockdown evaluates all the controllers thereby forcing ActiveScaffold to add lot of meta programming which in turn makes db queries to find out the column definitions of every model. This is considerably slowing down the request in development as there is no class_caching. Some times are requesting are taking almost 30-45 seconds.
Is there any way to force ActiveScaffold to do its magic in a before_filter? Something like the following:
class SomeController < ApplicationController
before_filter :init_active_scaffold
private
def init_active_scaffold
self.class_eval do
active_scaffold :model
end
end
end
class SomeController < ApplicationController
before_filter :init_active_scaffold
private
def init_active_scaffold
self.instance_eval do
active_scaffold :model
end
end
end
class SomeController < ApplicationController
before_filter :init_active_scaffold
private
def init_active_scaffold
self.class.class_eval do
active_scaffold :model
end
end
end
class SomeController < ApplicationController
before_filter :init_active_scaffold
private
def init_active_scaffold
self.class.instance_eval do
active_scaffold :model
end
end
end
I tried all the above four options, when I make a request, browser seem to show the loading indicator but nothing is happening.
Any help is appreciated.
Thanks in advance.
Lockdown only reparses init.rb in development mode so you can make changes without restarting the application. It will be slower - a convenience trade off. Good news is that Lockdown will only do this parsing once in production mode.
I don't use ActiveScaffold, so I can't offer any help there, but thought this would be of interest to you.