2013-04-19 14 views
6

rozważyćCzy można poprosić o tylko niektóre kolumny ze stowarzyszenia ActiveRecord?

def Foo 
    has_one :user 
end 

powiedzmy chcę tylko wymienić Foo 's User' s, a nie któregokolwiek z pozostałych kolumn. więc chcę

SELECT name FROM "users" WHERE "prices"."id" = 123 

ale robi foo.user.name da mi

SELECT * FROM "users" WHERE "prices"."id" = 123 

jest jakiś zręczny sposób na wykorzystanie stowarzyszenie uzyskać tylko jedną kolumnę? jeśli nie, to muszę zrobić:

User.where(id: foo.user_id).pluck(:name).first 

Odpowiedz

4

Ogólnie można określić, jakie kolumny chcesz wybrać się metodą .Wybrać, jak:

User.select(:name).where(...) 

To zwróci tylko te wartości z nazwa kolumny. Możesz powiązać to z powiązaniem, ale nie z instancją. Tak więc, jak bardzo bardzo agresywnie wskazano meagar przez odrzucenie innych odpowiedzi (w tym usuniętej odpowiedzi Mori), w relacji has_one nie można powiązać tego z powiązaniem (ponieważ nie jest to w tym przypadku asocjacja). Jednakże, można zbudować zakres niestandardowych, takich jak to:

class Foo < ActiveRecord::Base 
    has_one :bar 
    scope :bar_name, lambda {Bar.select(:name).where(:foo_id=> id)} 
end 

Powyższe niesprawdzone więc może trzeba go podkręcić, ale ogólnie rzecz biorąc to podejście pozwoli Ci zrobić coś takiego:

foo.bar_name 

... bez ładowania wszystkich kolumn z paska.

+0

Czy zakres mógłby być reprezentatywny? Zakres zwykle zwraca ActiveRecord :: Relation, pusty lub nie. Metoda byłaby bardziej odpowiednia (lub delegowana?) – MrYoshiji

+0

Cóż, jest to łańcuch metod kwerend ActiveRecord, więc myślę, że zwraca relację - jedyną dziwną rzeczą jest to, że zwróci relację zbudowaną na klasie Bar z klasy Foo - ale gdy już przejdziesz do 'something.otherthing.where()' i tak to robisz. Zdefiniowanie metody byłoby również dobrym sposobem, aby to osiągnąć. Nigdy nie musiałem robić czegoś takiego, więc nie mam ram odniesienia, który byłby lepszy lub dlaczego. – Andrew

1

Nie, w przypadku Twojego has_one, ale tak w przypadku has_many.

Obiekt zwrócony dla skojarzenia has_one nie jest zasięgiem, na którym można łączyć dodatkowe metody, takie jak select, podobnie jak z has_many. Jest to faktyczna instancja modelu, a jej utworzenie musi koniecznie obejmować select *.

Jeśli chcesz wybrać tylko nazwę, musisz uzyskać bezpośredni dostęp do modelu User i użyć select.

Odwrotnie, jeśli Foo ma wiele users, można użyć foo.users.select("name") lub którykolwiek z pozostałych metod chainable, jak foo.users byłoby rzeczywisty ActiveRecord stowarzyszenie, a nie instancją modelu.

Powiązane problemy