【问题标题】:How to use two controllers with one model in Rails如何在 Rails 中使用两个控制器和一个模型
【发布时间】:2012-12-03 11:29:40
【问题描述】:

我有一个订单模型。客户通过 Orders 控制器与 Order 模型进行交互。管理员通过 Purchases 控制器与 Order 模型进行交互。

大部分情况下它都在工作,除了发生这种情况:

  1. 管理员用户转到 new_purchase_path
  2. 应用程序使用购买控制器中的“创建”操作,如 预计
  3. 然后应用程序使用订单控制器中的“新”操作(而不是 采购控制人)
  4. 然后应用呈现“app/purchases/new”视图(而不是 “app/orders/new” 视图),尽管它已切换到使用订单控制器
  5. 在管理员创建订单后,应用程序会呈现 使用订单控制器的“app/orders/show”视图

我真正需要的是:

  1. 管理员用户转到 new_purchase_path
  2. 应用然后使用购买控制器中的“创建”操作
  3. 应用然后使用购买控制器中的“新”操作
  4. 然后应用呈现“app/purchases/new”视图
  5. 在管理员创建订单后,应用程序会呈现 使用购买控制器的“app/purchases/show”视图

在 app/controllers/purchases_controller.rb 我有这个:

  def new
    @purchase = Order.new
    respond_with @purchase
  end

如果尝试过类似...的变体

  def new
    @purchase = Order.new
    respond_with @purchase, :controller => :purchases
  end

...但是对于respond_with,没有类似的记录,自然它不起作用。我能做什么?

【问题讨论】:

  • 我不知道你为什么有respond_with 尝试删除它。另外,我不确定我是否理解事件的流程,特别是 2 和 3。你是什么意思它使用购买#create,然后使用订单#new。如果用户转到 new_purchase_path,purchase#new 是被调用的操作。
  • @todd 这个问题令人困惑,因为它基于前一个问题,其中存在一些混乱(部分是我的错):stackoverflow.com/questions/13676834/… 我已经在那里更新了我的答案,并在此处添加了一个答案我想解释了发生了什么。

标签: ruby-on-rails


【解决方案1】:

一些观察:

  1. 您不应在新操作中使用 *respond_with*,因为它对 HTML 以外的任何内容都没有任何意义。
  2. 如果您只想为管理员制作一些控制器,您应该使用命名空间。见http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing。这样您也无需更改名称。

【讨论】:

  • +1 建议使用命名空间作为此问题的替代解决方案。
  • 所以,让我检查一下我明白了。消费者通过全局命名空间中的订单控制器与订单模型交互。管理员用户与 admin 命名空间中的二阶控制器进行交互。而且当用户进入 admin/order#new 时,不会有任何戏剧性的事件——然后流程将自然地进入 admin/order#create,然后是 admin/order#show,没有任何令人讨厌的 hack 以确保这确实发生。对吗?
【解决方案2】:

这个问题的答案与你的last question有关。我已经更新了my answer there,但简而言之,问题不在于respond_with(正如@jiri-pospisil 指出你并不真正需要的那样),而在于simple_form_for 生成的表单。该表单中的操作网址默认为/orders,因为@purchaseOrder 类的一个实例。

要解决这个问题,请在表单中指定 url:

= simple_form_for @purchase, :as => :purchase, :url => purchases_path(@purchase) do |f|
  = f.error_notification
  = f.input :name
  = f.button :submit

然后你会发现你还有一个问题:新订单(购买)创建后,respond_with 会重定向到OrdersControllershow action。要解决这个问题,您可以使用location 选项:

def create
  @purchase = Order.new(params[:purchase])
  if @purchase.save
    respond_with(@purchase, :location => purchases_path(@purchase))
    ...

此时您可能已经知道,以这种方式将两个控制器用于单个模型会变得有些复杂,因此您可能需要考虑使用namespaces

【讨论】:

  • 谢谢。这确实让我按照最后的要求返回购买#show。有趣的是,当 purchase#new 呈现购买/新视图时,它仍然显示创建订单按钮,而不是创建购买按钮。奇数。
  • 是的,我打算添加一个关于此的注释。原因是form_for 使用Order 类来为提交按钮找到合适的文本。通常您可以通过在config/locales.yml 的正确位置添加文本来自定义它,但它会在与(再次)类对应的位置查找字符串,因此如果您覆盖它,它也会更改提交按钮订单表格。基本上,你是在逆向工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-30
  • 2016-06-23
  • 2012-08-09
  • 1970-01-01
相关资源
最近更新 更多