ruby-on-rails 在“不同”控制器的方法之间传递参数

f0ofjuux  于 2023-02-06  发布在  Ruby
关注(0)|答案(3)|浏览(188)

关于如何在同一控制器的方法之间传递参数,已经有一些线程。
但是有没有一种方法可以在不同控制器的方法之间传递参数呢?
因为有时候你有一个文章,当你对它调用#update操作时,你还希望同时通过TagsController的#update操作更新与它关联的标签。
这个习惯用法类似于在ArticlesController#操作中示例化TagsController,然后在执行tags_controller_instance.send(:update)操作时,将Rack::Response的一个新示例传递给它,其中只有整个params-hash的一部分:tags。
您必须只发送ArticlesController收到的params-hash的特殊部分,因为TagsController将具有不同的StrongParameters!
我认为这可以归结为一个问题,即如何创建一个Rack::Request,一方面复制ArticlesController的Request,另一方面如何传递给它而不是整个params-hash,而是其中有意义的部分。
然后应该可以在ArticlesController#update中使用this.tags请求更新后的标记列表,对吗?
谢谢
冯·斯波茨

cgyqldqp

cgyqldqp1#

这个习惯用法类似于在ArticlesController #操作中示例化TagsController,然后在执行tags_controller_instance. send(:update)时,将Rack::Response的一个新示例传递给它,该示例仅包含整个参数散列的一个:tags部分。
请不要这样做!这将很难理解和维护。可能还有其他副作用,你甚至没有想到太多。
问题是,TagsController#update做了什么你不想在ArticlesController中复制的事情?如果它是一些复杂的逻辑,我认为你应该抽象它,比如在(service) object中,然后调用它。
大概是这样的

class UpdateTags
  def self.run(params)
    new(params).run
  end

  def initialize(params)
    @params = params
  end

  def run
    # copy logic from TagsController
  end
end

然后您可以在控制器中使用/重用此服务

class TagsController
  def update
    UpdateTags.run(params)
  end
end

class ArticlesController
  def update
    # update Article or move this in a dedicated service too
    UpdateTags.run(params)
  end
end

另一种方法可以是让Article接受Tags的属性和nested attributes

编辑

详细说明一下为什么示例化另一个控制器不是一个好主意。

  • 那么before过滤器呢?(再次)执行它们可以吗?
  • 那么视图渲染呢?你显然不想渲染视图,所以这是额外的工作,可能会有副作用?
  • 其他副作用,如缓存、日志记录、数据分析。
  • 示例化控制器不是一个公共API,因此这可能会在Rails版本之间发生变化,从而使更新变得困难。
  • 这不是一个常见的模式,所以很难理解

我只想再次强调,这不是一个好主意,重复的代码比错误的抽象要好。

vxf3dgd4

vxf3dgd42#

这听起来像是Wile E. Coyote对一个用nested attributes解决的微不足道的问题的疯狂解决方案。
在Rails中,控制器的唯一公共方法应该是控制器的 * actions *,它们是响应HTTP请求的方法,并且这些 * 只能通过http调用来调用 *。
任何其他方法 * 都应该是private/protected *。没有有效的方案可以让您从另一个控制器调用TagsController#update来更新标记,因为该方法should do only one thing-update tags响应PATCH /tags/:id
如果您想在一个请求中更新一篇文章及其标签,请使用accepts_nested_attributes_for :tags

class Article < ApplicationRecord
  has_many :tags
  accepts_nested_attibutes_for :tags
end

这将创建一个tags_attributes= setter,您可以使用它来更新嵌套记录和父记录。
如果你想在不适合传统继承的类之间共享功能,那么就使用水平继承。在Ruby中,这意味着模块:
一个一个一个一个一个x一个一个二个一个x一个一个三个一个x一个一个x一个四个一个
在某些情况下,你可能会选择使用AJAX来创建/更新/删除嵌套资源,通过发送异步HTTP请求来调用另一个控制器(但不在同一个请求中)。

zu0ti5jz

zu0ti5jz3#

如果您在许多控制器中使用参数,只需将它们添加到应用程序控制器的私有方法中。

相关问题