在has_one关系的:select选项中使用lambda

时间:2011-11-22 20:19:10

标签: ruby-on-rails ruby-on-rails-3 activerecord ruby-on-rails-3.1 arel

我想在has_one的{​​{1}}关系查询中选择其他字段。

问题是:每次触发select查询时都必须评估select查询的内容,因为我得到了存储过程的附加字段的值,我需要在运行时传递一个参数。

我会想象它会以某种方式工作:

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)

1 个答案:

答案 0 :(得分:0)

我的解决方案

我找到的一个可能的解决方案是对模型进行子类化并覆盖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)

在我的特殊情况下,这很好,因为我不是一直都不需要存储过程的值,现在只能查询我需要它的情况。

希望这有助于其他任何人。 :)