【问题标题】:How to make a model aware of its controller in Rails?如何让模型知道它在 Rails 中的控制器?
【发布时间】:2012-10-03 17:31:49
【问题描述】:

我正在制作一个 Rails 应用程序,我希望能够使用传递给视图的模型对象来获取对该对象执行某些操作的 URL,例如:

link_to object.public_send(attribute),
        { :controller => object.controller_path,
          :action     => :show,
          :id         => object.id }

有什么好的方法可以做到这一点?可以用Draper这样的装饰器来完成吗?网上有例子吗?


更新。我考虑过这一点,并认为装饰器不是保存控制器信息的好地方。这不是装饰者的责任。装饰器应该只知道使用标记呈现格式化数据。现在我已经创建了一个名为Accessor 的模块,我尝试将模型与控制器和路由感知混合在一起。我仍然想知道是否有更好的方法。

【问题讨论】:

  • 你能解释一下你为什么需要它吗?也许这是你可以用 url_for 做的事情?
  • 谢谢,这与我想要的很接近,但我已经尝试过了。 url_for 的一个大问题是它依赖于 polymorphic_url,它对模型一无所知,并依赖 Inflector 来猜测控制器名称。不能使用自定义名称。小问题是我可能希望有不同的控制器在不同的情况下管理相同的模型。
  • 你能举个例子说明你需要这个吗?似乎您想要多个演示者课程,但根据您要完成的任务,这可能有点过分
  • 现在我只想将模型或“装饰模型”传递给共享视图,并在视图中处理所有与模型相关的链接。我想知道装饰器是否是添加控制器感知(路由感知)的合适位置。

标签: ruby-on-rails decorator


【解决方案1】:

如果您不介意视图上有另一个实例变量,您可以使用一个非常简单的类来实现它(不需要装饰器)。

class MyRouter
  def initialize(controller, object)
    @controller = controller
    @object     = object
  end

  def url_for(action_name)
    controller.url_for(object, :action => action_name)
  end
end

在您的控制器上:

class AController
  def edit
    @router = MyRouter.new(self, object)
    render 'shared_view'
  end
end

class BController
  def edit
    @router = MyRouter.new(self, object)
    render 'shared_view'
  end
end

在您的共享视图上:

<%= @router.url_for(:show) # Varies with the controller that rendered the view %>

当然,这假设您想要作为目标的控制器与呈现视图的控制器相同,这可能不是真的。不过,使用这种模式,您可以适应更复杂的逻辑以满足您的需求(例如,具有多个 Router 类),而无需更改视图。

【讨论】:

  • 在我的例子中,目标控制器更多地依赖于模型类而不是当前控制器,并且可能有几个对象传递给视图,每个对象都应该指向自己的控制器的链接。
  • 每个对象的目标控制器如何变化?它是由呈现共享视图的控制器决定的吗?还是有其他标准?
  • 当前控制器决定哪些“家庭”控制器与哪些模型类相关联。但在大多数情况下,它们仅依赖于模型类。
【解决方案2】:

我在 Avdi Grimm 的 Objects on Rails 中找到了一个非常有趣的解决方案:Exhibits for REST。简而言之,他的想法是应用多个 Ruby 的SimpleDelegators 作为具有各种功能的装饰器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 1970-01-01
    • 2011-08-07
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多