2010-12-30 17 views
5

Jestem super nowym użytkownikiem w RoR. Teraz pracuję nad tym interesującym ćwiczeniem Rails dla zombie. I utknąłem z kilkoma pytaniami składni ...Pytanie o składnię Ruby on Rails

Mój kod to:

Weapon.where(:zombie => "Ash") 

Ale to nie będzie działać. Jeśli zamiast tego wpisałem:

Weapon.find(1) 

Minąłem (ponieważ pierwsza broń należy do popiołu zombie).

Moje pytanie brzmi, co jest nie tak z moją odpowiedzią z tą metodą .where()?

Z góry dziękuję.

alt text

alt text

alt text

+1

Oto link do samouczka, dla zainteresowanych: http://railsforzombies.org/ –

+0

Dziękuję za zadanie pytania.Utknąłem w tej samej części, a odpowiedzi tutaj (szczególnie te z ravi i DGM) wyjaśniły mi powód. – Gerry

Odpowiedz

8

Trzeba zagnieżdżone zapytania następująco:

Weapon.where(:zombie => {:name => "Ash"}) 

Że daje bronie należące do zombie o imionach: "Popiół"

+0

To wygląda na nadzieję, że ... :) –

2

Nie jestem pewien, również nowy w Rails3 zapytań, ale robi : zombie oczekiwać, aby dopasować obiekt zombie, a nie jego nazwa.

zrobiłbym Zombie.where(:name => "Ash").weapons

+0

dzięki Chris. ale wydaje się, że relacja * weapon * nie została ustanowiona w klasie Zombie (chociaż powinna być). więc mam "#

+1

Wypróbuj' Zombie.where (: name => "Ash"). weapon' jeśli jest to jeden do jednego związku. –

2

generalnie używać Model.find() jeśli potrzebna jest pojedynczy obiekt i zwraca nil jeśli nie znaleziono. Podczas gdy Model.where({:field => value}) zwraca tablicę obiektów, które są zgodne z warunkiem.

+1

Po prostu pęknięcie: Technicznie, w szynach 3, nie zwraca tablicy. Zwraca "ActiveRecord :: Relation" (który koncepcyjnie jest zbiorem elementów, ale nie utworzono jeszcze zapytania). Railsy 3 pozwalają łączyć te relacje, a otrzymasz odpowiedź tylko wtedy, gdy zadzwonisz do find_all lub każdego z nich. Nawet wtedy wynikiem nie jest tablica, ale moduł wyliczający. – DGM

3

Jeśli chcesz WHERE ty Teraz zwraca pojedynczą wartość, a następnie można napisać

Zombie.where(:name => "ash").first 
+0

Nie sądzę, ponieważ pytanie prosi o "wszystko" –

+0

@Chris Właściwie to działa, wystarczy dodać .weapons na końcu, aby dołączyć do modelu broni. – Gerry

+0

Ups - dzięki @Gerry - dobry punkt. –

1

Ponieważ stół zombie jest powiązany z bronią ble, można użyć następującego kodu: Zombie.find (1) .weapons.all

FYI - Zombie ID 1 = Ash

4

Jeśli, tak jak ja, starali się to poprzez próbę Zombie Model, będziesz musiał użyć metody najpierw. To dlatego, że gdzie() zwraca kolekcję zombie.

tj

Zombie.where(:name => "Ash").first.weapons 

Ten poradnik wciąż uczy starej składni hash, ale odkąd Ruby 1.9 można (i należy) używać nowego formatu uproszczonej.Składnia ta działa nawet w tutorialu Zombies:

Zombie.where(name:"Ash").first.weapons 
1
Zombie.where(:name => "Ash").first.weapons 

IMHO: Myślę, że w ten sposób jest bardziej wyraźne: po pierwsze, szukamy zombie, a potem - chce wziąć pierwszy za broń.

pewno Ci może szukać broni przez id zombie (Weapon.where (: zombie_id => SOME_ZOMBIE_ID)), ale jak dla mnie - to nie jest rzecz, którą chcesz zobaczyć w moim kodzie pół roku po - chodzi o więcej kodowania i marnowanie czasu na zrozumienie.

PS: Wydaje się, że moja odpowiedź jest krótsza wersja odpowiedzi Gerry (patrz wyżej) - przepraszam za to :)

1

w tym kontekście u można wypróbować ten kod:

z = Zombie.find("ID") 
Weapon.where(:zombie_id => z) 
+0

i do następnego ćwiczenia, jeśli chcesz policzyć wszystkie bronie, które należą do "Popiołu" w prosty typ: z.weapons.count –

2

ten sposób zamierzają Państwo to zrobić (na podstawie filmu)

popiół = Zombie.find (1) ash.weapons

Który powinien zwrócić tablicę wszystkich broni s ash posiada. Próbowałem tak długo, aby użyć metody liczenia, a następnie zdałem sobie sprawę, że chcieli tylko rzeczywistych przedmiotów z bronią (tablica/lista/cokolwiek to jest, dopiero zaczynam tory od C++ i tło Pythona)

0

Myślę, że zdałeś używając Weapon.find(1), ponieważ w stoliku broni była tylko jedna broń, ale jeśli utworzysz kolejną broń, z: id => 1, twoja oryginalna składnia nie zadziałałaby - ponieważ zwróciłaby tylko pierwszą broń, a nie całą broń.

Zdałem, używając, Zombie.find(1).weapons, który zwróci wiele wpisów dla broni związanych z: id = 1, ale również myślał tak samo jak ty i chciał wyszukiwać według: name i nie: id.

Byłem też myśleć o użyciu atrybutu „gdzie”, ale nie może zmusić go do pracy - i kiedy stosować @edgerunner odpowiedzieć powrócił:

#<ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: zombie.name: SELECT "weapons".* FROM "weapons" WHERE "zombie"."name" = 'Ash'> 

więc nie jestem pewien, czy to jest ograniczeniem poprzez program lub co - jak to jest, jestem jeszcze trochę zdezorientowany.

+0

"Zombie.find_by_name (" Ash ") .weapons działa i używa atrybutu name, ale nie sądzę, że ** find_by_name ** zostało jeszcze omówione – Brett

1
Weapon.whe­re(:zombie­_id => Zombi­e.where(:n­ame => "Ash"­)) 

Można wybrać DB broni The zombie_id którego nazwa jest popiół z DB Zombie.

2

Natrafiłem dziś na ten sam problem, ale przyjęta odpowiedź nie zadziałała. Nie wiem, czy API zmieniła się od 2010 roku, ale mam go do pracy w ten sposób:

Weapon.joi­ns(:zombie­).where(:z­ombies => {:nam­e => "Ash"­}) 

Można również uzyskać ten sam rezultat poprzez łączenie w innym kierunku, chociaż myślę, że pierwsze rozwiązanie jest co pytanie szukał:

Zombie.whe­re(:name => 'Ash'­).first.we­apons 
0

odpowiedź jest Zombie.find(1).weapons .. następnie będzie sukcesem znaleźć Uzbrojenie wszystkie Asha.