2011-01-09 9 views
17

W modelu zawartości ma atrybut o nazwie slug. Podczas tworzenia nowego rekordu chcę użyć pomocnika do wypełnienia tego pola, ale w istniejącym rekordzie chcę użyć wartości z bazy danych.Railsy - domyślna wartość w text_field, ale tylko dla new_record?

Obecnie mam:

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

Ale to wydaje się nieco rozwlekły. Czy to najlepszy sposób, czy nie ma innej drogi? (Szyny newb po prostu staramy się znaleźć "Rails sposób" w kwestiach jestem pewny)


Edycja

Należy zauważyć, że pomocnik jest obecnie w/app/pomocników/application_helper .rb Przeniesiono do prywatnego działania w sterowniku Contents. Odpowiedź Davida była świetna.

Odpowiedz

24

W kontrolerze

@content.slug ||= generate_slug(6) 

Będzie to przypisać wartość atrybutu slug jeśli brak takowych

Następnie w widoku można po prostu użyć

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

To wygląda świetnie. Jak mogę udostępnić pomocnika w kontrolerze? (generate_slug (6) jest pomocnikiem). Otrzymuję 'niezdefiniowaną metodę' generate_slug 'dla # ' – jyoseph

+0

Zarysuj, że dodałem ją jako prywatną akcję do kontrolera Contents. Nie przejmuj się mną! Dziękuję za odpowiedź! – jyoseph

+0

Jak zauważył carpeliam, w zależności od tego, jak i jak często będziesz używać tej funkcji, możesz chcieć umieścić model jako metodę ('def slug; slug || = generate_slug (6); end) . –

0

Opcje

  1. Spróbuj after_initialize wywołania zwrotnego w swoim modelu.
  2. Spróbuj utworzyć metodę w swoim modelu, w której ustawisz wartości domyślne i wywołasz ją w swojej nowej akcji w kontrolerze. Wywołaj tę metodę, jeśli twoja instalacja się nie powiedzie i wyrenderujesz nową. Pamiętaj, aby ustawić wartość domyślną tylko wtedy, gdy nie ma żadnej wartości, używając operatora || =.

Przykład do naśladowania. Piszę na telefonie!

+1

'after_initialize' prawdopodobnie nie jest najlepszym wyborem, ponieważ będzie on również wywoływany za każdym razem, gdy pobierzesz obiekt z bazy danych. Chyba że tego chcesz? –

0

Używam jQuery w moich projektach, więc gdy chcę mieć taką funkcjonalność, zwykle używam czegoś takiego jak labelify. Następnie użyłbym czegoś takiego jak <%= f.text_field :slug, :title => generate_slug(6) %>. (Gorąca wskazówka, nie musisz wstawiać połączenia #generate_slug do ciągu znaków, jeśli zwróci coś, co samo się rozwiąże, w rzeczywistości jest bardziej wydajne, jeśli tego nie zrobisz.)

Jeśli nie chcesz iść z podejściem jQuery, możesz chcieć zawrzeć ten kawałek logiki w swoim modelu.

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 

Jeśli to rzeczywiście należy w widoku, jeszcze innym rozwiązaniem jest po prostu dokonać Ruby trochę bardziej zwięzły (będziesz musiał ocenić, czy jest to bardziej czytelne):

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

Nie zapomnij o parens otaczających (generate_slug(6) if @content.new_record?). Jeśli to zrobisz, if zostanie zastosowany do pola tekstowego, co nie jest tym, czego potrzebujesz.

Ale wciąż jest więcej sposobów na zrobienie tego. Powyższy wiersz kodu nie jest świetny, jeśli twoja logika może się zmienić i wklejasz ten kod do całego projektu rails.Kiedy chciałem dodać "wymaganą" klasę do moich pól tekstowych, ale tylko wtedy, gdy były one nowym rekordem (mieliśmy starsze dane, których nie chcieliśmy oczyścić), stworzyłem własny kreator formularzy z required_field metoda, która właśnie nazwała text_field i dodała "wymaganą" klasę, jeśli element był nowym rekordem. To może wydawać się dziełem, ale mamy około 20 różnych formularzy, z których każda zawiera potencjalnie wiele wymaganych pól, a logika biznesowa jest o wiele łatwiejsza w jednym miejscu. Więc jeśli naprawdę myślisz, że ta logika należy do widoku, ale masz masę tych linii kodu i nie chcesz jej zmieniać w milionach miejsc, to FormBuilder jest drogą do zrobienia. Myślę, że jest to w większości przypadków ładniejsze i bardziej odpowiednie niż pomocnik, ale znowu piękno jest w oku patrzącego. Oto mój kod nieco dostosowany do twojego przypadku:

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

Mam nadzieję, że we wszystkich tych różnych podejściach pasuje do Twojego projektu.

+0

Nie mam uprawnień do zostawiania komentarzy na temat odpowiedzi Davida, ale wydaje się, że jest to miejsce, w którym możesz chcieć zastosować "Kontroler chudego modelu tłuszczu". http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model – carpeliam

+0

Skomentowałem moją odpowiedź na ten temat. Chociaż powinno to zostać wprowadzone do modelu tylko wtedy, gdy jest często używane. Jeśli (np.) Jest używany tylko jako domyślny atrybut w jednym miejscu (np. Użytkownik wybrał kulę przy rejestracji, z domyślnym warunkiem dla niego) powinien wejść do kontrolera w (tylko) tej konkretnej akcji. –

Powiązane problemy