【问题标题】:Rails - default value in text_field but only for new_record?Rails - text_field 中的默认值,但仅适用于 new_record?
【发布时间】:2011-01-09 04:27:00
【问题描述】:

在内容模型上有一个名为slug 的属性。创建新记录时,我想使用帮助程序填充此字段,但在现有记录上我想使用数据库中的值。

目前我有:

<% if @content.new_record? %>
  <%= f.text_field :slug, :value => "#{generate_slug(6)}" %>
<% else %>
  <%= f.text_field :slug %>
<% end %>

但这似乎有点冗长。这是最好的方法,还是没有其他方法? (Rails newb 只是试图在我不确定的问题上找到“Rails 方式”)


编辑

我应该注意到,助手当前在 /app/helpers/application_helper.rb 中移动为 Contents 控制器中的私有操作。大卫的回答效果很好。

【问题讨论】:

    标签: ruby-on-rails erb


    【解决方案1】:

    在你的控制器中

    @content.slug ||= generate_slug(6)
    

    这将为slug 属性分配一个值(如果不存在)

    那么,在你看来,你可以简单地使用

    <%= f.text_field :slug %>
    

    【讨论】:

    • 这看起来很棒。如何使我的助手在控制器中可访问? (generate_slug(6) 是一个助手)。我得到 undefined method generate_slug' 的 #<0x1037431b0>
    【解决方案2】:

    选项

    1. 在您的模型中尝试 after_initialize 回调。
    2. 尝试在模型中创建一个方法,在其中设置默认值并在控制器的新操作中调用它。如果您的创建失败并且您呈现新的,也请调用此方法。请记住,只有在不存在值时才使用 ||= 运算符设置默认值。

    示例如下。我在手机上打字!

    【讨论】:

    • after_initialize 可能不是您最好的选择,因为每次您从数据库中检索对象时都会调用它。除非那是你想要的?
    【解决方案3】:

    我碰巧在我的项目中使用 jQuery,所以当我想要一些类似的功能时,我通常使用类似 labelify 的东西。然后,我会使用&lt;%= f.text_field :slug, :title =&gt; generate_slug(6) %&gt; 之类的东西。 (热点提示,如果 #generate_slug 调用返回的内容会自行解析为字符串,则不需要将调用放在字符串中,事实上,如果不这样做,它的性能会更高。)

    如果您不想使用 jQuery 方法,您可能希望将这段逻辑包装在您的模型中。

    def Content < ActiveRecord::Base
      def slug
        self.new_record? ? self.slug_for_new_record : attributes[:slug]
      end
    
      private
      def slug_for_new_record
        # I don't know what you're doing in generate_slug, but it sounds model-
        # related, so if so, put it here and not in a helper
      end
    end
    

    如果它真的属于视图,还有一个选择是让你的 Ruby 更简洁一点(你必须判断这是否更具可读性):

    <%= f.text_field :slug, :value => (generate_slug(6) if @content.new_record?) %>
    

    不要忘记(generate_slug(6) if @content.new_record?) 周围的括号。如果这样做,if 将应用于 text_field,这不是您想要的。

    但还有更多方法可以做到这一点。如果您的逻辑可能会发生变化并且您将此代码粘贴到您的 Rails 项目中,那么上面的代码行就不是很好。当我想在我的文本字段中添加一个“必需”类时,但前提是它们是新记录(我们有一些不想让人们清理的遗留数据),我创建了自己的表单构建器,带有 @ 987654328@ 刚刚调用 text_field 的方法,如果项目是新记录,则添加一个“必需”类。这看起来像是一项工作,但我们有大约 20 种不同的表单,每个表单都可能有多个必填字段,并且在一个地方更改业务逻辑要容易得多。因此,如果您真的认为该逻辑属于视图,但您有大量这些代码行并且您不想在一百万个地方更改它,那么 FormBuilder 就是要走的路。我认为在大多数情况下,这比帮手更漂亮、更合适,但同样,美丽在旁观者的眼中。这是我的代码在某种程度上适合您的情况:

    # config/environment.rb
    ActionView::Base.default_form_builder = NamespacesAreFun::FormBuilder
    
    # lib/namespaces_are_fun/form_builder.rb
    module NamespacesAreFun
      class FormBuilder < ActionView::Helpers::FormBuilder
        def slug_field(method, options = {})
          opts = options.to_options
          opts.merge!(:value => generate_slug) if self.object.new_record?
          text_field(method, opts)
        end
      end
    end
    
    # views/.../your_view.html.erb
    <%= f.slug_field :slug %>
    

    希望所有这些不同的方法都适合您的项目。

    【讨论】:

    • 我无权将 cmets 留在 David 的回答中,但这似乎是您可能想要应用“Fat Model Skinny Controller”的地方。 weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model
    • 我对此发表了评论。尽管只有在经常使用时才应将其放入模型中。如果(例如)它仅在一个地方用作默认属性(例如,用户在注册时选择了一个 slug,并为他提供了默认值)它应该(仅)在该特定操作中进入控制器。
    猜你喜欢
    • 2019-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    相关资源
    最近更新 更多