2013-05-22 8 views
27

Piszę interfejs Railsowy do zarządzania zapasami. Chcę, aby użytkownicy mogli zarejestrować produktów, więc mam:Szyny opcjonalne belongs_to

class User < ActiveRecord::Base 
    has_many :products 
    # <snip> 
end 

i

class Product < ActiveRecord::Base 
    belongs_to :user 
    # <snip> 
end 

Problemem jest to, że produkty są tworzone przed zarejestrowanych przez użytkownika. Oznacza to, że można zadzwonić pod numer Product.create i po prostu ustawić go na user_id na nil. Jak można sobie wyobrazić, choć Rails nie obsługuje tego z pudełka:

> Product.create! 
    (0.3ms) SELECT COUNT(*) FROM "products" WHERE "products"."type" IN ('Product') 
    (0.1ms) begin transaction 
    (0.1ms) rollback transaction 
ActiveRecord::RecordInvalid: Validation failed: User can't be blank 
    from ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-3.2.13/lib/active_record/validations.rb:56:in `save!' 

Myślałem o bandą kludgey obejścia, z których najbardziej atrakcyjne jest mieć NullUser instacji User i wykorzystanie do tworzenia produktów. Ale to wciąż wygląda na włamanie. Co to jest Rails Way?

Dzięki.


Odpowiedni migracja:

class AddUseridToProducts < ActiveRecord::Migration 
    def change 
    add_column :products, :user_id, :integer 
    end 
end 

i później:

class Changeuseridtobeoptionalforproducts < ActiveRecord::Migration 
    def change 
    change_column :products, :user_id, :integer, null: true 
    end 
end 
+0

Poinformuj wszystkie weryfikacje, które masz na temat modelu "produktu". –

Odpowiedz

4

Czy masz weryfikację, która wymaga obecności użytkownika? Jeśli tak, usuń to.

3

Szyny absolutnie obsługuje tej wyjęciu z pudełka, sprawdzić migrować masz włączone ograniczenie takie jak :null => false na linia user_id? Jeśli tak, wyjmij go!

Edytuj: Lub jako @Rodrigo Dias states, odwróć go do :null => true.

Sprawdź również, czy nie ma żadnych sprawdzeń dotyczących relacji użytkownika w modelu produktu.

+1

lub po prostu przełącz na: null => true –

+0

Dodałem moją migrację do OP (nie wkleiłem tutaj, ponieważ przerwy w linii by umarły). – tsm

+0

Wykonałem migrację z 'change_column: products,: user_id,: integer, null: true', ale to nic nie dało. – tsm

108

właśnie aktualizacja dla szyn 5, jeśli chcesz tego rodzaju zachowanie będzie trzeba przekazać tę opcję:

belongs_to :user, optional: true 

W Rails 5, gdy definiujemy asocjację belongs_to, wymagane jest, aby mieć powiązany rekord domyślnie obecny.

+1

Ughhh ... wszyscy powinniśmy przeczytać informacje o wydaniu ... ? –

+0

Próbowałem tego w szynach 5, widzę jego opcjonalne, ale problem jest, jeśli wprowadzę nieistniejącej wartości w polu klucza obcego, to akceptuje go. W takim przypadku powinien wywołać błąd, który nie jest dostępny w głównej tabeli. Jak to naprawić? –

+0

Możesz to zrobić z jakąkolwiek relacją, wierzę, że cokolwiek umieścisz spróbuje zrobić to na nim, jeśli nie jest to liczba lub zero. Powinieneś używać metod instancji, które należą do podania, tworzenie powiązań za pomocą tej metody zapobiegnie niepoprawnym wartościom, użyj Association.users.build i User.build_association, aby również uniknąć nieistniejących rekordów zostało powiązane, w moim przypadku, w którym używam opcjonalnej wartości true dla skojarzonego użytkownika z określonym rekordem, ten rekord dopuszcza użytkowników gości, więc właśnie robię Association.user = current_user, jeśli current_user jest zerowe, nie otrzymam błędu – Alexis

Powiązane problemy