Pass a variable to Rails controller method
I'm modifying the MobileFu plugin for Rails (https://github.com/brendanlim/mobile-fu) to accept an argument for whether to turn the plugin on or not.
In the controller, you call something开发者_运维技巧 like:
class ApplicationController < ActionController::Base
has_mobile_fu
end
But I would like to do:
class ApplicationController < ActionController::Base
has_mobile_fu :mobile_enabled
def mobile_enabled
current_account.mobile_enabled?
end
end
Where current_account is set by a subdomain lookup. The problem is, when I pass in :mobile
, it only passes in the symbol, not the value of :mobile
.
Here's the relevant MobileFu code: https://github.com/brendanlim/mobile-fu/blob/master/lib/mobile_fu.rb
And here's my edit:
def has_mobile_fu(enabled, options = {})
include ActionController::MobileFu::InstanceMethods
logger.info "Enabled is: " + enabled.to_s
before_filter(options) do |controller|
controller.set_mobile_format(enabled)
end
helper_method :is_mobile_device?
helper_method :in_mobile_view?
helper_method :is_device?
end
If I call this with a static argument in the controller (i.e. has_mobile_fu(false)
), it works fine. It's when I'm trying to pass in a variable (i.e. has_mobile_fu :mobile_enabled
) that I'm running into trouble. The variable just comes in as a symbol (so the logger output above would be Enabled is: mobile_enabled
.
Thanks!
Here's a sketch of an idea. I always like to make methods "smart". So the user of the method (you) won't need to think too much. It should just work. With that in mind:
# 1: Modify has_mobile_fu to something like this:
def has_mobile_fu(enabler = false, &block)
include ActionController::MobileFu::InstanceMethods
enabler = block if block_given?
case enabler
when Proc
# Determine if we enable or not by calling proc
before_filter { |controller|
controller.set_mobile_format if enabler.call(controller)
}
when Symbol
# Call the method named by the symbol instead
before_filter { |controller|
controller.set_mobile_format if controller.send(enabler)
}
# Old behaviour below
when true
before_filter :force_mobile_format
else
before_filter :set_mobile_format
end
# Rest is like the old method...
...
end
With the above setup you use it like this:
class ApplicationController < ActionController::Base
# The old way
has_mobile_fu
# The old way, forcing mobile format
has_mobile_fu true
# The new way using a symbol that signifies a method to call
# to determine if we're enabling or not
has_mobile_fu :mobile_enabled
# The new way using an in-line proc method
has_mobile_fu { |controller| controller.mobile_enabled }
def mobile_enabled
...
end
end
This way it "just works". It's backwards compatible, and if you supply a symbol or a proc then those are used instead as methods that will be called to check if enable or not.
Note..code is untested, but hopefully you get the general idea.
Edit: simplified the code a bit...
Well there is a bit confusion here.
When you define
has_mobile_fu
in your controller, it's a Class Method, not an instance one.When you want to pass args to a method, consider it's a hash:
has_mobile_fu :mobile_enabled => "somevalue"
So in your method definition, if you have:
def has_mobile_fu args
You'll be able to get the value using args[:mobile_enabled]
Lastly, because you want to get a value depending on the current_account
, consider passing a Lambda.
精彩评论