开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜