Serialize - szukanie po id

Cześć.

Mam model Station i Line. Relacja jest serialize :stations, Array. Moje pytanie jest takie - jak sprawdzić czy dana stacja należy do danej lini?
Niby powinno się to robić tak:

Line.find(:all, :conditions => [“stations LIKE ?”, “%1%2%”])

Lecz takie zapytanie porównuje nawet z 15 czy 14 i je zwraca bo jest tu jedynka.

Mam jeden sposób ale dosyć żrący:

lines = []
Line.all.each do |line|
if line.stations.include?(1)
lines << line
end
end

Dzięki za wszelką pomoc. Pozdrawiam.

Hę? Korzystaj z normalnych relacji jak “has_many :through” :wink:

Serialize dlatego, że Line posiada czasami dośc dużo stacji i raczej tu nie pasuje nic innego. Może przykładowe rekordy pomogą zrozumieć mój problem.

#<Line id: 1, number: “1”, direction: “KUCELIN - SZPITAL”, stations: [57, 8, 249, 245, 72, 243, 3, 85, 49, 50, 260, 220, 262, 247, 54, 228, 257, 42, 138], created_at: “2011-04-07 18:24:35”, updated_at: “2011-04-07 18:24:35”>

Jak widać stations to tablica lecz w bazie danych to jest traktowane jak zwykły string. więc szukajać stacji Line.find(:all, :conditions => [“stations LIKE ?”, “%1%2%”]) szuka również tych 14, 15 , 22, 25 itd. Dodam, że serialize sprawia to, że w railsach taki string jest traktowany jak tabica.

Sql antypattern. Utrudniasz sobie życie mówiąć “Line posiada czasami dośc dużo stacji i raczej tu nie pasuje nic innego” (argument optymalizacyjny ??) i implementując to w ten sposób zatem nic dziwnego, że później musisz kombinować… Jak chcesz sobie embedować kolekcje w obiekcie to nie ta baza danych.

IMO nie ma znaczenia, czy Line może mieć pięć, czy tysiąc pięćset stacji, o ile masz model Station (a z tego, co napisałeś, masz) powinieneś powiązać te modele relacją - wrzucenie serializowanej tablicy do jednej z tabel relacją nie jest. Tylko wtedy będziesz mógł w pełni wykorzystać wbudowane w Railsy mechanizmy.

Rozumiem, że w grę wchodzi tutaj relacja wiele-wiele, więc najlepszym rozwiązaniem będzie has_many z opcią :through + model pośredniczący (np. LineStation, z atrybutami :line_id oraz :station_id).

[code=Ruby]# line.rb
class Line < ActiveRecord::Base
has_many :line_stations
has_many :stations, :through => :line_stations
end

line_station.rb

class LineStation < ActiveRecord::Base
belongs_to :line
belongs_to :station
end

station.rb

class Station < ActiveRecrord::Base
has_many :line_station
has_many :lines, :through => :line_stations
end[/code]
Wtedy będziesz mógł sobie wyszukiwać w ten sposób:

[code=Ruby]# dla Rails 3
Line.joins(:stations).where(‘stations.id’ => [1,5,8]) #=> [#<Line id: 2, …>, …]

dla Rails 2

Line.all(:joins => :stations, :conditions => {‘stations.id’ => [1,5,8]}) #=> [#<Line id: 2, …>, …][/code]
Jako bonus możesz poczytać trochę o normalizacji baz danych :wink:

Zawsze możesz spróbować z http://www.mongodb.org/. Będziesz mógł sobie ładnie zaembedować Station w Line i po nich wyszukiwać :slight_smile:

Dzięki za pomoc. Rozwiązanie GhandaL częściowo się sprawdza. Mam teraz problem z tym szukaniem, te sposoby na szukanie wyszukują wszystkich lini z każdą stacją podaną w tablicy. Czyli potrzebuje takiego zapytania by szukało lini która posiada te stacje, a nie jedną z nich.