Rails - значение по умолчанию в text_field, но только для new_record? - PullRequest
17 голосов
/ 09 января 2011

В модели содержимого есть атрибут с именем slug.При создании новой записи я хочу использовать помощник для заполнения этого поля, но в существующей записи я хочу использовать значение из базы данных.

В настоящее время у меня есть:

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

Но это кажется немного многословным.Это лучший способ или другого пути нет?(Rails newb просто пытается найти «путь Rails» по вопросам, в которых я не уверен)


Edit

Я должен отметить, чтоhelper в настоящее время находится в /app/helpers/application_helper.rb. Перемещен в качестве частного действия в контроллере содержимого.Ответ Дэвида отлично сработал.

Ответы [ 3 ]

24 голосов
/ 09 января 2011

В вашем контроллере

@content.slug ||= generate_slug(6)

Это присвоит значение атрибуту slug, если его нет

Тогда, на ваш взгляд, вы можете просто использовать

<%= f.text_field :slug %>
0 голосов
/ 09 января 2011

Я использую jQuery в своих проектах, поэтому, когда мне нужны некоторые функции, подобные этой, я обычно использую что-то вроде labelify . Тогда я бы использовал что-то вроде <%= f.text_field :slug, :title => generate_slug(6) %>. (Горячий совет: вам не нужно помещать вызов #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. Когда я хотел добавить «обязательный» класс к своим текстовым полям, но только если они были новой записью (у нас были некоторые устаревшие данные, которые мы не хотели заставлять людей очищать), я создал свой собственный конструктор форм с помощью required_field метод, который просто вызвал 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 %>

Надеюсь, что во всех этих разных подходах подходит тот, который подходит вашему проекту.

0 голосов
/ 09 января 2011

Опции

  1. Попробуйте call_initialize callback в вашей модели.
  2. Попробуйте создать метод в вашей модели, в котором вы установите значения по умолчанию и вызовите его в своем новом действии в контроллере. Также вызовите этот метод, если ваше создание не удалось, и вы рендерите новый. Не забудьте установить значение по умолчанию только в том случае, если значение не существует с помощью оператора || =.

Пример для подражания. Я печатаю на телефоне!

...