1

在我的 Rails 应用程序中,我需要在模块中使用 ApplicationController 中定义的方法。该模块还需要可供所有控制器/助手访问。我不确定让模块访问此方法的最佳方法是什么。我认为有一种方法可以通过包装模块然后将其包含到 ApplicationController 中来实现。

我还想保留命名空间,而不是将模块方法直接包含在控制器中。例如 controller.Module.foo 而不仅仅是 controller.foo

这就是我想要做的:

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

现在我知道我可以向 Analytics 模块添加一个 self.included 方法,它为我提供传入的基础对象,但我不知道如何在 KissMetrics 模块中使用该基础。

这是可能的还是有更好的方法来做到这一点?

编辑:

为了进一步澄清,我使用了一个扩展/包含在 ActionController::Base 中的 gem。请参阅此脚本的底部。然后在 ApplicationController 中配置这个库。我想要做的就是拥有一个包含使用此 gem 的已定义事件的模块。它使我更容易在我的所有控制器中拥有一致的事件,例如

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"
4

2 回答 2

0

据我所知,您不应该从库中调用控制器操作,而是反过来。

我建议创建一个库,因为我不知道您要构建什么我已经设置了一个示例:

在 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

所以现在在你的控制器中:

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
于 2013-03-12T16:46:10.217 回答
0

决定通过将模块更改为一个类并在 ApplicationController 的 before_filter 回调中实例化它来解决这个问题。我将初始化的分析对象传递给它,一切都很好。本来希望使用模块,但这可以解决问题。

于 2013-03-18T14:51:33.233 回答