Datamapper有n个和相关的查询

时间:2011-04-12 16:51:14

标签: ruby scope datamapper

这是我的数据模型:

class A
  has n, :b
  has n, :c, through => :b

 def active_c
   c.active
 end
end

class C
  class << self
    def active
        all(self.end_on => nil) + all(:conditions => [ "cs.end_on > applied_to" ])
    end
  end
end

SQL看起来像:

SELECT `cs`.`id` FROM `cs` INNER JOIN `bs` ON `cs`.`id` = `bs`.`c_id` INNER JOIN `as` ON `bs`.`a_id` = `as`.`id` WHERE (`bs`.`a_id` = 1672 AND `cs`.`end_on` IS NULL)
SELECT `cs`.`id` FROM `cs` INNER JOIN `bs` ON `cs`.`id` = `bs`.`c_id` INNER JOIN `as` ON `bs`.`a_id` = `as`.`id` WHERE (`bs`.`a_id` = 1672 AND (cs > applied_to))
SELECT `id`, `created_at`, `updated_at`, `applied_to`, `end_on` FROM `cs` WHERE (1 = 0 OR 1 = 0) GROUP BY `id`, `created_at`, `updated_at`, `applied_to`, `end_on` ORDER BY `id`

如果我将active_c更改为此impl:

 def active_c
   C.all(:bs  => {:a_id => self.id}).active
 end

调用a.active_c的结果SQL是:

SELECT `c_id` FROM `bs` WHERE `a_id` = 1670
SELECT `c_id` FROM `bs` WHERE `a_id` = 1670
SELECT `id`, `created_at`, `updated_at`, `applied_to`, `end_on` FROM `cs` WHERE ((1 = 0 AND `end_on` IS NULL) OR (1 = 0 AND (cs.end_on > applied_to))) ORDER BY `id`

现在有两个问题:

  1. 我必须在的第二个条件中使用cs.end_on,因为表还有一个名为end_on的列,DM会混淆
  2. 为什么有3个查询,1 = 0来自
  3. 由于

1 个答案:

答案 0 :(得分:1)

我已经尝试设置应该与您要实现的目标一致的工作模型,结果如下:

class A
  include DataMapper::Resource

  property :id, Serial

  has n, :bs
  has n, :cs, :through => :bs, :via => :c

  def active_cs
    cs.active
  end
end

class B
  include DataMapper::Resource

  property :id, Serial

  belongs_to :a
  belongs_to :c
end

class C
  include DataMapper::Resource

  property :id, Serial
  property :end_on, Date
  property :applied_to, Date

  has n, :bs

  def active
    all(:end_on => nil) + all(:conditions => [ "cs.end_on > applied_to" ])
  end
end

a = A.create
b = B.create(:a => a)
c = C.create(:b => b)

puts a.active_cs.inspect

这是SQL查询:

SELECT "id", "end_on", "applied_to" FROM "cs" WHERE ("id" IN (SELECT "cs"."id" FROM "cs" INNER JOIN "bs" ON "cs"."id" = "bs"."c_id" INNER JOIN "as" ON "bs"."a_id" = "as"."id" WHERE ("bs"."a_id" = 1 AND "cs"."end_on" IS NULL)) OR "id" IN (SELECT "cs"."id" FROM "cs" INNER JOIN "bs" ON "cs"."id" = "bs"."c_id" INNER JOIN "as" ON "bs"."a_id" = "as"."id" WHERE ("bs"."a_id" = 1 AND (cs.end_on > applied_to)))) GROUP BY "id", "end_on", "applied_to" ORDER BY "id"

我不确定这是否正是你所需要的 - 但我希望它有所帮助。

以下是使用工作脚本的gist链接:https://gist.github.com/916164