背景: 我有两个模型:
gin.rb
class Gin < ApplicationRecord
has_many :gins_botanical
has_many :botanicals, through: :gins_botanical
botanical.rb
class Botanical < ApplicationRecord
has_many :gins_botanical
has_many :gins, through: :gins_botanical
在查看给定植物的展示页面时,我想显示一个包含特定植物的杜松子酒列表。
我正在使用where子句来实现这一目标,但我无法让它发挥作用。
PG :: UndefinedTable:错误:缺少表的FROM子句条目 &#34;植物&#34;第1行:SELECT&#34; gins&#34;。* FROM&#34; gins&#34;哪里 (botanicals.name LIKE&#39;%an ... ^:SELECT&#34; gins&#34;。* FROM&#34; gins&#34; WHERE(botanicals.name LIKE&#39;%angelica root%&#39;)
我可以看到"%#{@botanical.name}%"
很好,因为它显示了当前植物的价值,在这种情况下,angelica root
,但很明显我并没有拉过其他也有的杜松子酒angelica root
作为一种植物。
botanicals_controller
def show
@similargins = Gin.where("botanicals.name LIKE ?", "%#{@botanical.name}%")
end
植物/ show.html.erb
<% @similargins.each do |gin| %>
<%= gin.name%>
<% end %>
答案 0 :(得分:2)
假设你的关联设置正确(你的关系并不明显),那么我想你可以这样做:
class Gin < ApplicationRecord
has_many :gin_botanicals
has_many :botanicals, through: :gin_botanicals
class << self
def with_botanicals(botanicals)
joins(:bontanicals).where(botanicals: {id: botanicals})
end
end
end
之前我已经说过了,我会再说一遍。有些人会更喜欢scope
到类方法。有些人会更喜欢self.with_botanicals
到class << self
。可以说,这些是偏好的问题。
然后,我们假设您有一个@gin
变量和一个@botanical
变量。您应该可以执行以下操作:
Gin.with_botanicals(@botanical).where.not(@gin)
这应该会为您提供@botanical
但不是@gin
的所有杜松子酒。您可以通过执行以下操作匹配所有@gin.botanicals
:
Gin.with_botanicals(@gin.botanicals).where.not(@gin)
如果你想找到与@gin
共有任何植物药的所有杜松子酒,那么这个鱼的水壶会略有不同(包括使用{{1} }})并适用于一个新问题。同样,您可以搜索所有含有名称IN
LIKE
的植物药的杜松子酒,但同样会遇到另一种问题。
答案 1 :(得分:1)
在查看给定植物的展示页面时,我想显示一个包含特定植物的杜松子酒列表。
简单。只是做:
@botanical = Botanical.includes(:gins).find(params[:id])
@gins = @botanical.gins
如果您已拥有ID,则无需LIKE
查询。而且由于你已经设置了间接关联,你可以用它来获取金币。
如果您真正想要的是获得与给定杜松子酒有共同植物成分的其他杜松子酒,您可以这样做:
class Gin < ApplicationRecord
has_many :gin_botanicals
has_many :botanicals, through: :gin_botanicals
def similiar_gins
Gin.joins(:botanicals)
.where(botanicals: { id: self.botanical_ids })
.where.not(id: self.id)
end
end
.joins
创建一个左内连接 - 所以在连接表中没有匹配的任何行都将被丢弃。
.where(botanicals: { id: self.botanical_ids })
创建一个WHERE IN
查询,要求联合记录至少有一个植物。
您还可以使用GROUP BY和HAVING:
设置所需的模拟度class Gin < ApplicationRecord
has_many :gin_botanicals
has_many :botanicals, through: :gin_botanicals
def similiar_gins(common_ingredients: 1)
Gin.joins(:botanicals)
.where(botanicals: { id: self.botanical_ids })
.where.not(id: self.id)
.group("gins.id")
.having("COUNT(distinct botanicals.id) >= ?", common_ingredients)
end
end
假设:
irb(main):039:0> Gin.all.pluck(:id, :name)
(1.1ms) SELECT "gins"."id", "gins"."name" FROM "gins"
=> [[1, "Beefeater Gin"], [2, "Bombay Sapphire"], [3, "Mockinghamshire"]]
irb(main):040:0> Botanical.all.pluck(:id, :name)
(1.1ms) SELECT "botanicals"."id", "botanicals"."name" FROM "botanicals"
=> [[1, "Almond"], [2, "liquorice"], [3, "Foo"]]
irb(main):041:0> GinBotanical.all.pluck(:gin_id, :botanical_id)
(0.5ms) SELECT "gin_botanicals"."gin_id", "gin_botanicals"."botanical_id" FROM "gin_botanicals"
=> [[1, 1], [2, 1], [1, 3], [1, 2], [2, 2]]
有两种常见成分:
irb(main):036:0> Gin.first.similiar_gins(common_ingredients: 2)
Gin Load (1.2ms) SELECT "gins".* FROM "gins" ORDER BY "gins"."id" ASC LIMIT $1 [["LIMIT", 1]]
(4.0ms) SELECT "botanicals".id FROM "botanicals" INNER JOIN "gin_botanicals" ON "botanicals"."id" = "gin_botanicals"."botanical_id" WHERE "gin_botanicals"."gin_id" = $1 [["gin_id", 1]]
Gin Load (4.3ms) SELECT "gins".* FROM "gins" INNER JOIN "gin_botanicals" ON "gin_botanicals"."gin_id" = "gins"."id" INNER JOIN "botanicals" ON "botanicals"."id" = "gin_botanicals"."botanical_id" WHERE "botanicals"."id" IN (1, 2, 3) AND ("gins"."id" != $1) GROUP BY gins.id HAVING (COUNT(distinct botanicals.id) >= 2) [["id", 1]]
=> #<ActiveRecord::Relation [#<Gin id: 2, name: "Bombay Sapphire", created_at: "2018-03-07 23:44:43", updated_at: "2018-03-07 23:44:43">]>
但是如果我们将它设置为3,我们得到一个空集:
irb(main):037:0> Gin.first.similiar_gins(common_ingredients: 3)
Gin Load (0.7ms) SELECT "gins".* FROM "gins" ORDER BY "gins"."id" ASC LIMIT $1 [["LIMIT", 1]]
(1.8ms) SELECT "botanicals".id FROM "botanicals" INNER JOIN "gin_botanicals" ON "botanicals"."id" = "gin_botanicals"."botanical_id" WHERE "gin_botanicals"."gin_id" = $1 [["gin_id", 1]]
Gin Load (5.0ms) SELECT "gins".* FROM "gins" INNER JOIN "gin_botanicals" ON "gin_botanicals"."gin_id" = "gins"."id" INNER JOIN "botanicals" ON "botanicals"."id" = "gin_botanicals"."botanical_id" WHERE "botanicals"."id" IN (1, 2, 3) AND ("gins"."id" != $1) GROUP BY gins.id HAVING (COUNT(distinct botanicals.id) >= 3) [["id", 1]]
=> #<ActiveRecord::Relation []>
答案 2 :(得分:0)
最终这是一个非常简单的修复。有人昨晚发布了这个答案,但很快就将其删除了。
我需要一个简单的连接:
DECLARE @SESSION_START_DATE datetime
SET @SESSION_START_DATE = DATEADD(ms, 1520503133980 % 1000,DATEADD(ss, 1520503133980/1000, CONVERT(DATETIME2(3),'19700101')))
INSERT INTO EC_USER_SESSION(SESSION_START_DATE) VALUES(@SESSION_START_DATE);
所以现在,当在植物'当归根'的展示页面上,我有一个每个循环,向我展示任何其他在他们的植物中列出'当归根'的杜松子酒。