简体   繁体   English

Ruby模块中的访问控制器方法

[英]Access controller method in a Ruby module

In my Rails app, there is a method defined in the ApplicationController that I need to use in a module. 在我的Rails应用程序中,有一个我需要在模块中使用的ApplicationController中定义的方法。 This module also needs to be accessible to all controllers/helpers. 该模块还需要所有控制器/助手都可访问。 I'm not sure what the best way is to give the module access to this method. 我不确定最好的方法是使模块访问此方法。 I figure that there is a way to do it by wrapping the module and then including it into the ApplicationController. 我认为有一种方法可以通过包装模块,然后将其包含到ApplicationController中来实现。

I also want to retain the namespacing instead of including the module methods right into the controller. 我还想保留命名空间,而不是将模块方法直接包含在控制器中。 eg controller.Module.foo instead of just controller.foo 例如controller.Module.foo而不是controller.foo

This is what I'm trying to do: 这就是我想要做的:

module Analytics
  module Events
    extend self

    def create_event name
      # do some stuff
      controller_method name
    end
  end
end

class ApplicationController < ActionController::Base
  include Analytics

  def controller_method
     # ...
  end

  def some_other_method
    Events.create_event :test
  end
end

Now I know I can add a self.included method to the Analytics module which gives me the passed in base object, but I don't know how I can make use of that base in the KissMetrics module. 现在,我知道可以在Analytics模块中添加self.included方法,该方法为我传递了传入的基础对象,但是我不知道如何在KissMetrics模块中利用该基础。

Is this possible or is there a better way of doing this? 这可能吗,还是有更好的方法呢?

Edit: 编辑:

To further clarify, I am using a gem that is extended/included into ActionController::Base. 为了进一步阐明,我使用的是一个扩展/包含在ActionController :: Base中的gem。 See bottom of this script . 请参阅此脚本的底部。 This library is then configured inside the ApplicationController. 然后在ApplicationController内部配置该库。 All I want to do is have a module with defined events that makes use of this gem. 我要做的就是拥有一个带有定义事件的模块,该模块利用了这个gem。 It makes it easier for me to have consistent events across all my controllers eg 这使我更容易在所有控制器上进行一致的事件,例如

module Events
  def sign_up_event
    analytical.event "sign up" # calls the library that was loaded into the app controller
  end
end

# in some controller
Events.sign_up_event
# instead of this, which is totally usable but not DRY
analytical.event "sign up"

As far as my knowledge goes, you shouldn't call a controller action from a lib but the other way around. 就我所知,您不应从lib中调用控制器动作,而应从相反的角度进行。

I suggest making a library as I do not know exactly what you are trying to build I've setup an example: 我建议制作一个库,因为我不知道您到底要构建什么,所以我建立了一个示例:

in lib/analytics.rb 在lib / analytics.rb中

class Analytics
  def initialize(object_id, event_id)
    # insert object to event relation logic here
    @object = Object.find(object_id)
    @event = Event.find(event_id)
  end

  def add_instance_method
    # add logic for instantiated Analytics object
    @object.event_collection.create(event_id: @event.id)
  end

  def self.check_class_method?(object_id, event_id)
    # check logic for Analytic Class taking 2 arguments
    @object = Object.find(object_id)
    @event = event.find(event_id)
    @object.events.include?(@event)
    # return true/false
  end
end

so now in your controller: 所以现在在您的控制器中:

def action
  @object = Object.find(params[:id])
  @event = Event.find_by_identifier("logged_in")

  unless Analytics.check_class_method?(@object_id, @event_id)
    analytic = Analytics.new(@object.id, @event.id)
    raise "Failed" unless analytic.add_instance_method
  end
end

Decided to solve this by changing the module into a class and instantiating it in a before_filter callback in ApplicationController. 决定通过将模块更改为类并在ApplicationController的before_filter回调中对其进行实例化来解决此问题。 I pass it the initialized analytical object and all is good. 我将初始化的分析对象传递给它,一切都很好。 Would have preferred using a module but this does the trick. 本来希望使用模块,但这可以解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM