Rails: 查找所有未通过join连接的资源table
Rails: find all resources not already connected through join table
我正在尝试重写将产品连接到项目和从项目断开连接的操作。目前我的 select_to_project
视图显示所有产品,但我希望它只显示尚未连接到给定项目的产品。
产品和项目通过联接连接 table
class Product < ActiveRecord::Base
has_and_belongs_to_many :projects, :join_table => "projects_products"
end
class Project < ActiveRecord::Base
has_and_belongs_to_many :products, :join_table => "projects_products"
end
class ProjectsProduct < ActiveRecord::Base
attr_accessible :project_id, :product_id
belongs_to :project
belongs_to :product
end
在我的产品控制器中,我目前有:
def select_to_project
@project = Project.find(params[:id])
@products = Product.find(:all)
end
def select_from_project
@project = Project.find(params[:id])
end
显然 select_to_project
视图当前显示所有可能的产品,甚至是那些已经通过连接 table.
连接的产品
我认为 select_to_project
动作应该改成这样:
def select_to_project
@project = Project.find(params[:id])
@products = Product.joins(:projects => :products).where('products_projects_join.product_id IS NOT ?', @product)
end
但是我目前在尝试加载相对视图时遇到 MySQL 错误:
Mysql::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1)' at line 1: SELECT `products`.* FROM `products` INNER JOIN `projects_products` ON `projects_products`.`product_id` = `products`.`id` INNER JOIN `projects` ON `projects`.`id` = `projects_products`.`project_id` INNER JOIN `projects_products` `products_projects_join` ON `products_projects_join`.`project_id` = `projects`.`id` INNER JOIN `products` `products_projects` ON `products_projects`.`id` = `products_projects_join`.`product_id` WHERE (products_projects_join.project_id IS NOT 1)
如何让这个查询在 Rails 3 中工作?
非常感谢您。
更新
感谢@Sebastian Palma 现在构建了视图,但查询结果不正确。
@products = Product.joins(:projects => :products).where('products_projects_join.project_id != ?', @project.id).uniq.order(:id, :order => 'id ASC')
产生以下查询:
SELECT DISTINCT 'products'.* FROM 'products' INNER JOIN 'projects_products' ON 'projects_products'.'product_id' = 'products'.'id' INNER JOIN 'projects' ON 'projects'.'id' = 'projects_products'.'project_id' INNER JOIN 'projects_products' 'products_projects_join' ON 'products_projects_join'.'project_id' = 'projects'.'id' INNER JOIN 'products' 'products_projects' ON 'products_projects'.'id' = 'products_projects_join'.'product_id' WHERE (products_projects_join.project_id != 2) ORDER BY id, '--- \n:order: id ASC\n'
我有 14 个产品条目,项目 2 已经连接到其中的 4 个。
projects_products_id / project_id / product_id
3 2 1
4 2 2
5 2 3
6 2 12
我的查询应显示 ID 为:4、5、6、7、8、9、10、11、13、14 的产品。
当前显示产品 3、4、5、6、7、8、9、10、12、13。
产品 14 当前未出现在联接 table 中,3 和 12 已连接,11 未连接。
相当于查询结果向左滑动了一个id值
理想情况下,我想找到产品 table 中尚未连接到给定项目的连接 table 的所有条目。
您已将关联设置为 has_and_belongs_to_many
,但 HABTM 是无头的,因此实际上也没有连接模型。
相反,您想将关联设置为 has_many through:
并使用常规名称 table。
首先将连接 table 重命名为 project_products
并确保它有一个 id 列。
class Product < ActiveRecord::Base
has_many :project_products
has_many :projects, through: project_products
end
class Project < ActiveRecord::Base
has_many :project_products
has_many :products, through: project_products
end
class ProjectProduct < ActiveRecord::Base
attr_accessible :project_id, :product_id
belongs_to :project
belongs_to :product
end
这会让你通过协会加入project_products
。
最简单的方法是执行子查询。在 Rails 的现代版本中,你会这样做:
Product.where.not(
id: project.products
)
创建以下查询:
SELECT "products".* FROM "products"
WHERE "products"."id" NOT IN (
SELECT "products"."id" FROM "products"
INNER JOIN "project_products" ON "products"."id" = "project_products"."product_id"
WHERE "project_products"."project_id" =
) LIMIT
然而 where.not
是在 Rails 4.0 中引入的。作为解决方法,您可以在 Rails 3.
中使用字符串
class Product < ApplicationRecord
has_many :project_products
has_many :projects, through: :project_products
def self.not_assigned_to_project(project)
Product.where("
products.id NOT IN (#{project.products.select(:id).to_sql})
")
end
end
我正在尝试重写将产品连接到项目和从项目断开连接的操作。目前我的 select_to_project
视图显示所有产品,但我希望它只显示尚未连接到给定项目的产品。
产品和项目通过联接连接 table
class Product < ActiveRecord::Base
has_and_belongs_to_many :projects, :join_table => "projects_products"
end
class Project < ActiveRecord::Base
has_and_belongs_to_many :products, :join_table => "projects_products"
end
class ProjectsProduct < ActiveRecord::Base
attr_accessible :project_id, :product_id
belongs_to :project
belongs_to :product
end
在我的产品控制器中,我目前有:
def select_to_project
@project = Project.find(params[:id])
@products = Product.find(:all)
end
def select_from_project
@project = Project.find(params[:id])
end
显然 select_to_project
视图当前显示所有可能的产品,甚至是那些已经通过连接 table.
我认为 select_to_project
动作应该改成这样:
def select_to_project
@project = Project.find(params[:id])
@products = Product.joins(:projects => :products).where('products_projects_join.product_id IS NOT ?', @product)
end
但是我目前在尝试加载相对视图时遇到 MySQL 错误:
Mysql::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1)' at line 1: SELECT `products`.* FROM `products` INNER JOIN `projects_products` ON `projects_products`.`product_id` = `products`.`id` INNER JOIN `projects` ON `projects`.`id` = `projects_products`.`project_id` INNER JOIN `projects_products` `products_projects_join` ON `products_projects_join`.`project_id` = `projects`.`id` INNER JOIN `products` `products_projects` ON `products_projects`.`id` = `products_projects_join`.`product_id` WHERE (products_projects_join.project_id IS NOT 1)
如何让这个查询在 Rails 3 中工作?
非常感谢您。
更新
感谢@Sebastian Palma 现在构建了视图,但查询结果不正确。
@products = Product.joins(:projects => :products).where('products_projects_join.project_id != ?', @project.id).uniq.order(:id, :order => 'id ASC')
产生以下查询:
SELECT DISTINCT 'products'.* FROM 'products' INNER JOIN 'projects_products' ON 'projects_products'.'product_id' = 'products'.'id' INNER JOIN 'projects' ON 'projects'.'id' = 'projects_products'.'project_id' INNER JOIN 'projects_products' 'products_projects_join' ON 'products_projects_join'.'project_id' = 'projects'.'id' INNER JOIN 'products' 'products_projects' ON 'products_projects'.'id' = 'products_projects_join'.'product_id' WHERE (products_projects_join.project_id != 2) ORDER BY id, '--- \n:order: id ASC\n'
我有 14 个产品条目,项目 2 已经连接到其中的 4 个。
projects_products_id / project_id / product_id
3 2 1
4 2 2
5 2 3
6 2 12
我的查询应显示 ID 为:4、5、6、7、8、9、10、11、13、14 的产品。
当前显示产品 3、4、5、6、7、8、9、10、12、13。
产品 14 当前未出现在联接 table 中,3 和 12 已连接,11 未连接。
相当于查询结果向左滑动了一个id值
理想情况下,我想找到产品 table 中尚未连接到给定项目的连接 table 的所有条目。
您已将关联设置为 has_and_belongs_to_many
,但 HABTM 是无头的,因此实际上也没有连接模型。
相反,您想将关联设置为 has_many through:
并使用常规名称 table。
首先将连接 table 重命名为 project_products
并确保它有一个 id 列。
class Product < ActiveRecord::Base
has_many :project_products
has_many :projects, through: project_products
end
class Project < ActiveRecord::Base
has_many :project_products
has_many :products, through: project_products
end
class ProjectProduct < ActiveRecord::Base
attr_accessible :project_id, :product_id
belongs_to :project
belongs_to :product
end
这会让你通过协会加入project_products
。
最简单的方法是执行子查询。在 Rails 的现代版本中,你会这样做:
Product.where.not(
id: project.products
)
创建以下查询:
SELECT "products".* FROM "products"
WHERE "products"."id" NOT IN (
SELECT "products"."id" FROM "products"
INNER JOIN "project_products" ON "products"."id" = "project_products"."product_id"
WHERE "project_products"."project_id" =
) LIMIT
然而 where.not
是在 Rails 4.0 中引入的。作为解决方法,您可以在 Rails 3.
class Product < ApplicationRecord
has_many :project_products
has_many :projects, through: :project_products
def self.not_assigned_to_project(project)
Product.where("
products.id NOT IN (#{project.products.select(:id).to_sql})
")
end
end