Как изменить сложный запрос SQL ж / объединить в рельсы 3 - PullRequest
1 голос
/ 08 октября 2010

Я работаю над приложением пула автомобилей, где пользователи могут добавлять лифты и выбирать несколько остановок для каждого лифта (от A до B с помощью c, d, e). Теперь, когда пользователь ищет в базе данных данные о лифтах, результаты также должны включать лифты, такие как «от A до D», «от C до B» или «от C до E» и т. Д.

Я получил это, работая с Rails 2.3.5, используя приведенный ниже код, но изо всех сил стараюсь перевести его на Rails 3. Я уверен, что должен быть более чистый способ достичь того, что я пытаюсь сделать, и перенести некоторый код в модель.

было бы замечательно, если бы кто-то мог помочь мне в этом.

class Lift < ActiveRecord::Base
  has_many :stops
end

class Stop < ActiveRecord::Base           
  belongs_to :lift
  belongs_to :city  
end

class City < ActiveRecord::Base
  has_one :stop
end


@lifts = Lift.find(
  :select =>     "lifts.id, bs.city_id as start_city_id, bs2.city_id as destination_city_id",
  :from =>       "lifts",
  :joins =>      "LEFT JOIN stops bs ON lifts.id = bs.lift_id
                  LEFT JOIN stops bs2 ON lifts.id = bs2.lift_id
                  JOIN cities bc ON bs.city_id = bc.id
                  JOIN cities bc2 ON bs2.city_id = bc2.id",
  :include =>    [:stops, :cities],
  :conditions => "bs.lift_id = bs2.lift_id AND bs.position < bs2.position"
                  #uses the position attribute to determine the order of the stops
)

Ответы [ 2 ]

0 голосов
/ 09 октября 2010

Я немного озадачен тем, что вы используете команды find: select и: include вместе. Я точно знаю, что: select игнорируется, когда вы используете: include (хотя, думаю, был плагин, чтобы это исправить). Кроме того, вы включаете: города, отношения, которые не отображаются в вашем коде.

В любом случае, если вы хотите добавить некоторые области в модель Lift, я бы подумал о переходе на API Arel, который является предпочтительным методом в Rails 3. http://m.onkey.org/2010/1/22/active-record-query-interface

Вы можете объединить весь запрос в одну область (не думайте, что вам нужна опция: from - может быть ошибочной):

class Lift
...
  scope :with_all_stops, select('lifts.id, bs.city_id as start_city_id, bs2.city_id as destination_city_id').\
                         joins('LEFT JOIN stops bs ON lifts.id = bs.lift_id ' +
                               'LEFT JOIN stops bs2 ON lifts.id = bs2.lift_id ' +
                               'JOIN cities bc ON bs.city_id = bc.id ' +
                               'JOIN cities bc2 ON bs2.city_id = bc2.id').\
                         includes(:stops, :cities).\
                         where('bs.lift_id = bs2.lift_id AND bs.position < bs2.position')
...
end

Тогда просто позвоните в Lift.with_all_stops. Или вы можете создать цепочку на своих условиях: Lift.with_all_stops.where ('towns.name = "Topeka"'). Это действительно мощно.

Если есть части этого запроса, которые полезны сами по себе (сомнительно в данном конкретном случае), вы можете разбить их на их собственные области, а затем соединить их все вместе, когда вы звоните. Или соедините их вместе в другой области и просто назовите это. Как я уже сказал, Арель может быть очень могущественным.

0 голосов
/ 08 октября 2010

Я знаю, что это действительно простой ответ, но почему бы не создать область в модели с этими параметрами?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...