Использование лямбды в опции: select отношения has_one - PullRequest
0 голосов
/ 23 ноября 2011

Я хочу выбрать дополнительные поля в запросе отношения has_one в ActiveRecord.

Проблема заключается в следующем: содержимое запроса на выборку должно оцениваться при каждом запуске запроса на выборку,потому что я получаю значение дополнительного поля хранимой процедуры, и мне нужно передать параметр во время выполнения.

Я бы предположил, что он будет работать примерно так:

class User < ActiveRecord::Base

  has_one :profile, :select => lambda { "SELECT profiles.*, my_stored_procedure(#{Time.now}) as virtual_attribute" }

end

Я могуне использовать область видимости, потому что мне нужно предварительно выбрать это отношение, используя includes на родительской модели:

User.includes(:profile).find(1,2,3)

, а также в качестве предварительно выбранной модели второго уровня:

OtherModel.includes(:user => [ :profile ])

1 Ответ

0 голосов
/ 23 ноября 2011

Мое решение

Одним из возможных решений, которое я нашел, является создание подкласса модели и перезапись default_scope, который также может занимать блок.Я протестировал его, и он работает, как и ожидалось!

Но важно отметить, что это работает только в Rails 3.1, так как 3.0 не не принимает блоки для default_scopeМетод (они просто игнорируются).

Вот пример задействованных моделей:

class Other < ActiveRecord::Base

  has_many :users

end


class User < ActiveRecord::Base

  has_one :profile
  has_one :profile_with_relationship

end


class Profile < ActiveRecord::Base  
end


class ProfileWithRelationship < Profile

  set_table_name "profiles"

  default_scope do
    select("'#{Time.now}' as virtual_attribute")
  end

end

Теперь он работает даже с вложенными включениями:

Other.includes(:users => :profile_with_relationship).find(1)

Будетпроизводить:

Other Load (0.1ms)  SELECT "others".* FROM "others" WHERE "others"."id" = ? LIMIT 1  [["id", 1]]
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."other_id" IN (1)
ProfileWithRelationship Load (0.2ms)  SELECT '2011-11-23 11:34:15 +0100' as virtual_attribute, "profiles".* FROM "profiles" WHERE "profiles"."user_id" IN (1, 2, 3, 4, 5)

В моем особом случае это нормально, так как мне не нужны значения хранимого процесса не все время, и я могу запрашивать его сейчас только в тех случаях, когда он мне нужен.

Надеюсь, это поможет кому-то еще.:)

...