【问题标题】:would it be ok to create an instantiate an object in another controller?在另一个控制器中创建一个实例化对象可以吗?
【发布时间】:2016-05-06 23:59:19
【问题描述】:

我有一个客户控制器。在新动作中,我重定向到另一个页面,该页面属于页面控制器

class CustomersController < ApplicationController
  def new
    redirect_to register_path
  end 

是否可以像这样在注册操作中创建对象?

class PagesController < ApplicationController        
  def registration
    @customer = Customer.new
  end
end

【问题讨论】:

  • 当然可以,但不是很安静
  • 从技术上讲,您可以在任何地方实例化对象,尽管它可能不遵循一些最佳实践,如 REST(如 @kingguy 建议的那样)。你想做什么?您是否尝试将 /customers/new 路由更改为 /registration 或其他什么?因为如果是这种情况,你应该调整config/routes.rb
  • 我无法真正在客户控制器中创建对象,因为我试图从注册视图呈现新操作,我将新操作视图作为部分视图。注册视图的目的是包含用于创建选项卡的代码,当用户单击适当的选项卡时,它将呈现适当的注册视图
  • 如果我没看错的话,我通常会做的是在部分选项卡中包含 HTML,并将 (render) 部分包含在customers/new.html.erb 中。其他每个选项卡都可能是不同的控制器/操作,它们每个都会&lt;%= render 'application/special_tabs' %&gt;。除非……是浏览器中单个 HTML 页面中包含的所有选项卡的内容吗?然后当用户单击不同的选项卡时,您只是在使用 JavaScript 隐藏/显示部分而不加载页面?
  • 好吧,我这样做的方式是创建一个中间页面调用注册页面,这是页面控制器中的注册操作,然后我生成 html 代码以在该注册文件中创建 2 个选项卡,然后呈现新操作当用户单击选项卡时,将每种类型的用户作为每个选项卡的内容。我不确定这是否是一个好方法,因为我无法弄清楚将对象通过注册页面传递到每个新部分的逻辑

标签: ruby-on-rails ruby object model-view-controller controller


【解决方案1】:

我相信设置是这样的:您的应用程序中有一个客户模型,比如说一个代理。您的网站用户注册为其中一个,并且希望拥有一个 HTML 页面 (URL),同时提供两个选项。他们选择他们是哪一个并提交一些字段,比如姓名/电子邮件/密码。为了简单起见,不用费心用 JavaScript 来隐藏选项卡后面的东西,你有这样的东西:

**顾客** 姓名: ___________ 电子邮件: __________ 密码: _______ [提交] **代理人** 姓名: ___________ 电子邮件: __________ 密码: _______ [提交]

您有几个选项可以避免在 Rails 控制器中产生内疚感:

  1. 使用繁重的客户端 JavaScript。控制器上没有new 操作。 JavaScript 创建页面元素。 create 操作成为 JSON API 端点,从而避免了 Ruby 应用程序中的问题。这显然与我认为的今天的架构存在重大偏差。
  2. 当用户在选项之间切换时,使用一点 JavaScript 将正确的“部分”动态加载到 DOM 中。通过有效地将“页面”分离到两个控制器来避免问题中的潜在问题。 Pages→registration 操作不需要为视图设置任何实例变量。 JavaScript 处理部分加载。 (参见“link_to”和“远程”选项)
  3. 不要在同一个 HTML 页面中包含两种表单,只需默认一种,例如 Customer 一种,并提供一个链接以导航到 Agent 一种,例如选项卡中的链接,或“不是客户?注册为代理”之类的普通链接。在这种情况下,您有一个到 Ruby MVC 设计的简洁映射,每个页面都只是其相关控制器的new 操作。缺点是在两个选项之间切换的页面加载。这是最简单、最简单的选择……如果你能让老板同意 UX。 PS:如果你使用的是turbolinks,那么这个选项在浏览器中的“感觉”与选项(2)相差不远。
  4. 坚持您的设计

请记住,使用选项 (4) 处理错误情况和消息会很困难。你可以做到,但代码不会简单或易于维护。

如果选项 (4) 是必须的,一个简化可以是每个控制器上的 create 操作呈现它们自己的 new 以防出错。如果您从起始页面向代理→创建操作提交“代理”表单,但出现错误,则该操作以render 'new' 结束,以向用户显示代理→新页面。没有可见的“客户”表格。然后,您可以在其中添加一些选项 (3),并带有“不是代理?注册为客户”。表格下方的链接。这样做可以大大简化您的错误处理。

这会导致针对您的原始问题提出建议。欺骗。没有用于 new 操作(或 registration 操作)的 @customer 实例变量。对客户和代理表单使用部分,并将新对象传递给form_for,例如


pages/registration.html.erb

<%= render 'customers/new_form' %>
<%= render 'agents/new_form' %>

客户/new.html.erb

<%= render 'customers/new_form' %>

客户/_new_form.html.erb

<% form_for Customer.new do |f| %>
  <%# include the inputs shared with the edit action %>
  <%= render 'fields', f %> 
  <%= f.submit %>
<% end %>

客户/_fields.html.erb

<%# 'f' is one of the locals passed to the partial %>
<% f.input_field :name %>
<% f.email_field :email %>
<% f.password_field :password %>

客户/edit.html.erb

<% form_form @customer do |f| %>
  <%= render 'fields', f %>
  <%= f.submit %>
<% end %>

...那么您将遵循相同的模式:

  • agents/new.html.erb
  • agents/_new_form.html.erb
  • agents/_fields.html.erb
  • agents/edit.html.erb

【讨论】:

  • 非常感谢您的完整解释
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-24
  • 2018-12-13
  • 2017-09-30
  • 2017-06-22
  • 2010-12-07
  • 1970-01-01
  • 2014-12-05
相关资源
最近更新 更多