2011-01-09 9 views
17

En un modelo de contenido, tiene un atributo llamado slug. Al crear un nuevo registro, quiero usar un helper para llenar este campo, pero en un registro existente quiero usar el valor de la base de datos.Rieles: valor predeterminado en text_field pero solo para new_record?

Actualmente tengo:

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

Pero eso parece un poco prolijo. ¿Es esta la mejor manera, o no hay otra manera? (Rieles NEWB tratando de encontrar el "camino carriles" en temas que estoy seguro de)


Editar

Debo señalar que el ayudante se encuentra actualmente en/app/helpers/application_helper .rb Se movió para ser una acción privada en el controlador de contenido. La respuesta de David funcionó de maravilla.

Respuesta

24

En su controlador

@content.slug ||= generate_slug(6) 

Esto asignará un valor al atributo slug si ninguno está presente

Luego, en su opinión, sólo tiene que utilizar

<%= f.text_field :slug %> 
+0

Esto se ve increíble. ¿Cómo puedo hacer que mi ayudante sea accesible dentro del controlador? (generate_slug (6) es un ayudante). Obtengo el método 'undefined' generate_slug 'para # ' – jyoseph

+0

Scratch that, lo agregué como una acción privada en el controlador de contenido. ¡No me importa! ¡Gracias por la respuesta! – jyoseph

+0

Según lo observado por carpeliam, dependiendo de cómo y con qué frecuencia va a utilizar esta funcionalidad, es posible que desee incluir el modelo como un método ('def slug; slug || = generate_slug (6); end) . –

0

Opciones

  1. Pruebe after_initialize callback en su modelo.
  2. Intente crear un método en su modelo donde establezca los valores predeterminados y llámelo en su nueva acción en el controlador. También llame a este método si su creación falla y rinde nueva. Recuerde establecer el valor predeterminado solo cuando no exista ningún valor utilizando el operador || =.

Ejemplo a seguir. ¡Estoy escribiendo por teléfono!

+1

'after_initialize' probablemente no sea su mejor opción, ya que también se llamará cada vez que recupere un objeto de la base de datos. A menos que eso es lo que quieres? –

0

Yo uso jQuery en mis proyectos, así que cuando quiero algunas funcionalidades como esta, suelo usar algo como labelify. Entonces, usaría algo como <%= f.text_field :slug, :title => generate_slug(6) %>. (Consejo importante, no es necesario colocar la llamada #generate_slug dentro de una cadena si devuelve algo que se resolverá en una cadena por sí mismo, de hecho es más eficiente si no lo hace).

Si No quiero ir con el enfoque de jQuery, es posible que desee envolver esta pieza lógica en su modelo.

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 

Si realmente pertenece en la vista, otra opción es simplemente hacer su rubí un poco más concisa (que tendrá que juzgar si esto es más fácil de leer):

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

No olvides los parientes que rodean al (generate_slug(6) if @content.new_record?). Si lo hace, el if se aplicará al campo de texto, que no es lo que desea.

Pero todavía hay más formas de hacerlo. La línea de código anterior no es excelente si su lógica puede cambiar y está pegando este código en todo su proyecto de rieles.Cuando quería agregar una clase 'requerida' a mis campos de texto, pero solo si eran un registro nuevo (teníamos algunos datos heredados que no queríamos que la gente limpiara), creé mi propio creador de formularios con un required_field método que acaba de llamar text_field y agregó una clase 'requerida' si el elemento era un nuevo registro. Esto puede parecer un trabajo, pero tenemos alrededor de 20 formularios diferentes, cada uno con múltiples campos requeridos, y es mucho más fácil cambiar la lógica de negocios en un solo lugar. Entonces, si realmente crees que esta lógica pertenece a la vista, pero tienes muchas de estas líneas de código y no quieres tener que cambiarla en un millón de lugares, entonces FormBuilder es el camino a seguir. Creo que esto es en la mayoría de los casos más bonito y más apropiado que un ayudante, pero, de nuevo, la belleza está en el ojo del espectador. Aquí está mi código algo adecuado para su caso:

# 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 %> 

Esperemos que en todos estos diferentes enfoques es uno que se adapte a su proyecto.

+0

No tengo privilegios para dejar comentarios sobre la respuesta de David, pero este parece ser un lugar donde es posible que desee aplicar "Fat Model Skinny Controller". http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model – carpeliam

+0

Comenté mi respuesta a tal efecto. Aunque esto debería incluirse en el modelo solo si se usa con frecuencia. Si (por ejemplo) solo se utiliza como un atributo predeterminado en un solo lugar (por ejemplo, el usuario elige un slug en el registro, con un valor predeterminado proporcionado por él) debe ir en el controlador en (solo) esa acción específica. –

Cuestiones relacionadas