Próbuję znaleźć najlepszy sposób na ustawienie wartości domyślnych dla obiektów w Railsach.
Najlepsze, co przychodzi mi do głowy, to ustawienie wartości domyślnej w new
metodzie w kontrolerze.
Czy ktoś ma jakiś wkład, jeśli jest to dopuszczalne lub czy istnieje lepszy sposób na zrobienie tego?
ruby-on-rails
ruby
biagidp
źródło
źródło
Odpowiedzi:
„Prawidłowo” to niebezpieczne słowo w języku Ruby. Zwykle jest więcej niż jeden sposób na zrobienie czegokolwiek. Jeśli wiesz, że zawsze będziesz potrzebować tej domyślnej wartości dla tej kolumny w tej tabeli, ustawienie ich w pliku migracji bazy danych jest najłatwiejszym sposobem:
Ponieważ ActiveRecord automatycznie wykrywa właściwości tabeli i kolumny, spowoduje to ustawienie tego samego domyślnego w każdym modelu używającym go w dowolnej standardowej aplikacji Railsowej.
Jeśli jednak chcesz ustawić wartości domyślne tylko w określonych przypadkach - powiedzmy, że jest to model dziedziczony, który dzieli tabelę z innymi - to innym eleganckim sposobem jest zrobienie tego bezpośrednio w kodzie Railsów, gdy tworzony jest obiekt modelu:
Następnie, gdy zrobisz a
GenericPerson.new()
, zawsze przepłynie atrybut „Doe” do,Person.new()
chyba że zastąpisz go czymś innym.źródło
.new
metodą klasy. Omówienie tego posta na blogu na temat bezpośredniego wywoływania ActiveRecord.allocate
dotyczyło obiektów modelu ładowanych istniejącymi danymi z bazy danych. ( I to okropny pomysł, aby ActiveRecord działał w ten sposób, IMO. Ale to nie ma znaczenia).change_column_default :people, :last_name, nil
stackoverflow.com/a/1746246/483520change_column :people, :last_name, :string, default: "Doe"
W oparciu o odpowiedź SFEley, tutaj jest zaktualizowany / poprawiony dla nowszych wersji Railsów:
źródło
change_column
może być dość „strukturalne”, nie można wywnioskować operacji odwrotnej. Jeśli nie jesteś pewien, po prostu przetestuj go, uruchamiającdb:migrate
idb:rollback
zaraz potem. Zaakceptowano odpowiedź jako ten sam wynik, ale przynajmniej przyjęto!up
idown
jak opisano powyżej z @GoBustoPrzede wszystkim nie możesz przeciążać,
initialize(*args)
ponieważ nie jest to wywoływane we wszystkich przypadkach.Najlepszą opcją jest dodanie ustawień domyślnych do migracji:
Drugą najlepszą metodą jest umieszczenie w modelu wartości domyślnych, ale zadziała to tylko z atrybutami, które początkowo są zerowe. Możesz mieć problemy, tak jak ja z
boolean
kolumnami:Potrzebujesz,
new_record?
aby wartości domyślne nie zastępowały wartości załadowanych z bazy danych.Musisz
||=
powstrzymać Railsy przed nadpisywaniem parametrów przekazanych do metody initialize.źródło
after_initiation :your_method_name
... 2 użyćself.max_users ||= 10
after_initialize do
zamiastdef after_initialize
Możesz także spróbować
change_column_default
swoich migracji (testowane w Railsach 3.2.8):change_column_default Dokumentacja Rails API
źródło
Jeśli odnosisz się do obiektów ActiveRecord, masz na to (więcej niż) dwa sposoby:
1. Użyj: default parametru w DB
NA PRZYKŁAD
Więcej informacji tutaj: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
2. Użyj oddzwaniania
NA PRZYKŁAD
before_validation_on_create
Więcej informacji tutaj: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M002147
źródło
W Ruby on Rails v3.2.8, używając
after_initialize
wywołania zwrotnego ActiveRecord, możesz wywołać metodę w swoim modelu, która przypisze domyślne wartości dla nowego obiektu.Więc IMO powinno wyglądać mniej więcej tak:
Foo.bar = default_value
w tym przypadku, chyba że instancja zawieraattribute_whose_presence_has_been_validated
poprzednio zapisaną / aktualizację.default_value
Zostaną następnie wykorzystane w połączeniu z widoku do renderowania formularz używającdefault_value
dobar
atrybutu.W najlepszym razie jest to hacky ...
EDYCJA - użyj „new_record?” aby sprawdzić, czy tworzona jest instancja z nowego połączenia
Zamiast sprawdzać wartość atrybutu, użyj
new_record?
wbudowanej metody z railsami. Tak więc powyższy przykład powinien wyglądać następująco:To jest dużo czystsze. Ach, magia Railsów - jest mądrzejsza ode mnie.
źródło
after_initialize
tutaj polecasz callback? Dokumentacja Railsów dotycząca wywołań zwrotnych zawiera przykład ustawienia wartości domyślnejbefore_create
bez dodatkowego sprawdzania warunkówSubscription
after_initialize
zamiastbefore_create
wywołania zwrotnego, jest to, że chcemy ustawić domyślną wartość dla użytkownika (do użycia w widoku) podczas tworzenia nowych obiektów.before_create
Zwrotna jest wywoływana po użytkownik został doręczony nowego obiektu, pod warunkiem ich wejścia i złożony obiekt, dla stworzenia do sterownika. Następnie kontroler sprawdza wszelkiebefore_create
wywołania zwrotne. Wydaje się to sprzeczne z intuicją, ale to rzecz nomenklaturowa -before_create
odnosi się docreate
akcji. Utworzenie wystąpienia nowego obiektu nie powoduje jegocreate
powstania.Przynajmniej dla pól boolowskich w Railsach 3.2.6 będzie to działać podczas migracji.
Wstawienie
1
lub0
jako wartości domyślnej nie zadziała tutaj, ponieważ jest to pole logiczne. Musi to być wartość atrue
lubfalse
.źródło
Jeśli masz do czynienia z modelem, możesz użyć API Attriutes w Railsach 5+ http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute
wystarczy dodać migrację z odpowiednią nazwą kolumny, a następnie w modelu ustawić ją za pomocą:
źródło
Wygeneruj migrację i użyj
change_column_default
, jest zwięzły i odwracalny:źródło
Jeśli ustawiasz tylko wartości domyślne dla niektórych atrybutów modelu opartego na bazie danych, rozważyłbym użycie domyślnych wartości kolumn sql - czy możesz wyjaśnić, jakich typów domyślnych używasz?
Istnieje wiele podejść do tego, ta wtyczka wygląda na interesującą opcję.
źródło
Propozycja zastąpienia nowego / inicjalizacji jest prawdopodobnie niekompletna. Railsy będą (często) wywoływać alokację dla obiektów ActiveRecord, a wywołania alokacji nie spowodują wywołań inicjalizacji.
Jeśli mówisz o obiektach ActiveRecord, przyjrzyj się zastępowaniu after_initialize.
Te posty na blogu (nie moje) są przydatne:
Wartości domyślne Nie wywołano konstruktorów domyślnych
[Edycja: SFEley wskazuje, że Railsy faktycznie patrzą na domyślne w bazie danych, gdy tworzy instancję nowego obiektu w pamięci - nie zdawałem sobie z tego sprawy.]
źródło
Musiałem ustawić wartość domyślną, tak jakby została określona jako domyślna wartość kolumny w DB. Więc zachowuje się tak
Ponieważ wywołanie zwrotne after_initialize jest wywoływane po ustawieniu atrybutów z argumentów, nie było możliwości sprawdzenia, czy atrybut jest zerowy, ponieważ nigdy nie został ustawiony lub został celowo ustawiony na zero. Musiałem więc trochę zagrzebać się w środku i przyszedłem z tym prostym rozwiązaniem.
U mnie działa świetnie. (Rails 3.2.x)
źródło
Potencjalnie jeszcze lepszym / czystszym potencjalnym sposobem niż proponowane odpowiedzi jest nadpisanie akcesora, na przykład:
Zobacz „Nadpisywanie domyślnych metod dostępu ” w dokumentacji ActiveRecord :: Base i nie tylko ze StackOverflow na temat używania self .
źródło
I odpowiedział na podobne pytanie tutaj .. czysty sposób, aby to zrobić przy użyciu Rails attr_accessor_with_default
AKTUALIZACJA
attr_accessor_with_default został uznany za przestarzały w Railsach 3.2 .. zamiast tego możesz to zrobić za pomocą czystego Rubiego
źródło
attr_accessor_with_default
jest przestarzałe od rails> 3.1.0Jeśli mówisz o obiektach ActiveRecord, używam klejnotu „atrybut-domyślne”.
Dokumentacja i pobieranie: https://github.com/bsm/attribute-defaults
źródło
Możesz użyć klejnotu rails_default_value. na przykład:
https://github.com/keithrowell/rails_default_value
źródło
Możesz nadpisać konstruktora dla modelu ActiveRecord.
Lubię to:
źródło