【问题标题】:Best Practice for Creating a Modular Form Spanning Several Different Layouts创建跨越多个不同布局的模块化表单的最佳实践
【发布时间】:2013-08-22 18:38:24
【问题描述】:

我是 RoR 新手 (v3.2.13),我正在构建一个新站点/应用程序,该站点/应用程序有很多登录页面,分为 6-8 个不同的布局。布局以不断变化的顺序使用相似的元素,因此我使用局部和布局继承来适当地呈现每个页面。

我的问题是我的表单(位于每个页面的顶部)也不一致(例如,虽然一个页面可能只有“姓名”和“电子邮件”字段,但另一个页面将包含一个额外的“电话”字段,第三个可能还包括“密码”、“地址”和“国家”字段等),并且为每个页面构建不同的部分似乎是一种非常浪费的方法,DRY 明智的,更不用说它是多么无效,尤其是因为我预计未来会有大量新页面。

我已经彻底研究了表单的​​概念,但还没有提出我认为足够好的解决方案,这可能是因为我是新手。不幸的是,我没有任何代码要展示,因为我一直等到我决定开始编码的最佳方法。

到目前为止,我想出的是在 Haml 中使用 jQuery 和条件,我理解这两种方法都很幼稚,而我将每个字段编码为自己的部分将被视为反模式(或者 - 不是 Rails 3方式)。

是否存在与此类设计问题相关的最佳实践?是否有任何我错过的在线/其他资源可以为我指明正确的方向?

谢谢!

【问题讨论】:

  • 您能否提供更多关于您最终要做什么的背景信息?你的设计应该尽可能地反映意图,所以如果这些是登陆页面的各种排列,那么共享部分代码的解决方案是有意义的;相反,如果它们是具有完全不同目标的 8 页(一个注册时事通讯,另一个使用 Facebook 登录等),那么您并没有真正重复代码,而是重复使用它并且没有t 一个共享祖先(尽管抽象的表单构建器可能仍然是合适的)。
  • @coreyward,感谢您的询问:将有一个共同的祖先,即正如您所提到的,它们都是同一个通用着陆页的各种排列(它们都共享相同的页脚、页眉和逻辑)。为了回答您的问题,所有表单都旨在共享相同的目标,即将用户的详细信息发送到数据库以供将来通信。那里没什么好看的。

标签: ruby-on-rails ruby forms ruby-on-rails-3.2 partials


【解决方案1】:

我会通过构建一个包含所有元素的单一表单来解决这个问题,将其放在一个部分中,并将其包含在所有登录页面中。然后在每个登录页面的单独样式表中,隐藏您不想在该特定页面上使用的所有元素。

要解决验证的潜在问题(例如,您需要验证是否在请求时提供了密码),您可以创建一个配置文件(例如 config/initializers/landing_forms.rb),您可以在其中指定要包含在每个表单字段中的表单字段,然后生成该文件中的适当 CSS 并在您的验证中使用它,即:

landing_forms.rb

YourInitializer = {
  foo: [:email, :password],
  bar: [:email, :name, :address],
  baz: [:name, :phone]
}.with_indifferent_access.freeze

_form.html.erb

<%= form_for ... do |f| %>
  <%= f.hidden_field_tag :landing_page_id, value: 'foobar' %>
<% end %>

控制器

class UsersController < ApplicationController
  def create
    @user = User.new(params[:user])
    User.validate_only requested_fields
    # ...
  end
protected
  def requested_fields
    YourConfig.fetch params[:landing_page_id]
  end
end

型号

class User < ActiveRecord::Base
  attr_reader :required_validations
  validate :email, presence: true, if: :email_required?

  def email_required? # feel free to use a bit of metaprogramming to make this simpler
    required_validations.include? :email
  end

  def validate_only(fields)
    @required_validations = fields
  end
end

page_forms.css.erb

/* Hide all non-button inputs by default, then show individually */
<% YourConfig.each_pair do |landing_page_id, fields| %>
  <% fields.each do |field| %>
    #<%= landing_page_id %> form .<% field %> { display: block }
  <% end %>
<% end %>

希望这足以让您入门!

【讨论】:

  • 感谢您提供冗长而详细的解决方案,就像一个魅力!当我有足够的“声誉”来投票时,我会回来投票。
【解决方案2】:

这种结构怎么样?

# Controller
@fields = [:name, :country, :phone]

# View
@fields.each do |field|
   render "form/" + field.to_s
end

# form/name.html.erb
<%= text_field(:name) %>

【讨论】:

  • 在控制器中定义字段是有问题的。控制器应该尽可能少地了解数据是什么,而是专注于将请求数据与模型和渲染器/视图连接起来。
  • 我更喜欢这个而不是单独的配置文件。
  • @screenmutt,不幸的是我没有足够的“声誉”来投票给这个,但请注意这个解决方案也对我有用。我认为配置文件解决方案更像是“Rails 方式”,所以如果我要开发一个长期的、高质量的应用程序,我会首先选择这种方法,但如果我想要的话,我可能会选择你的方法一种快速而肮脏的方式来完成它。谢谢!
猜你喜欢
  • 2019-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-27
  • 1970-01-01
  • 1970-01-01
  • 2011-06-18
相关资源
最近更新 更多