简短版本:我需要使用自定义的内部连接来在一个表中找到id,其中两个字段在Rails的两个表中匹配,但是Rails内部连接对我不知道如何处理的关系做了假设。
长版本:我已经接管了一个Rails项目,它有一个非规范化的数据库。我将一些信息提取到一个新的表中,现在我需要遍历每个条目,并在原始表上放置一个外键,但是我很难找到正确的ActiveRecord查询来获取这些信息。
在这种情况下,集合属于存储库,存储库可能有许多集合。
该项目最初将所有集合和存储库存储在同一个表中,如果它是存储库,则为集合名称为NULL,如果是集合,则为存储库名称和集合名称。我创建了一个迁移,它使用了所有唯一的存储库名称,并将它们固定在存储库表中。现在,我需要做的是返回集合表,并根据string从匹配的存储库中添加id。
我在SQL中有一个查询,它提取正确的数据:
ActiveRecord::Base.connection.execute("SELECT r.id, r.repname FROM collections c, repositories r WHERE c.repname = r.repname")但是,我在与该对象交互时遇到了困难(对于#Mysql2 2::Result.“获取诸如”未定义的方法'last‘“之类的错误),我更希望知道在Rails模型中一切都是正确的。
当我尝试这个时,我会得到一个错误:
Repository.joins(:collections).where("collections.repname = repositories.repname")
Repository Load (1.0ms) SELECT `repositories`.* FROM `repositories` INNER JOIN `collections`
ON `collections`.`repository_id` = `repositories`.`id` WHERE (collections.repname = repositories.repname)
Mysql2::Error: Unknown column 'collections.repository_id' in 'on clause': SELECT `repositories`.* FROM `repositories` INNER JOIN `collections` ON `collections`.`repository_id` = `repositories`.`id` WHERE (collections.repname = repositories.repname)
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'collections.repository_id' in 'on clause': SELECT `repositories`.* FROM `repositories` INNER JOIN `collections` ON `collections`.`repository_id` = `repositories`.`id` WHERE (collections.repname = repositories.repname)我对Rails和SQL都很陌生,所以我认为我的问题实际上可能在于我如何建立模型。我正在使用数据库的现有命名conventions...maybe --我应该切换到Rails repository_id约定,而不是?
class Collection < ActiveRecord::Base
has_many :archive_object_collections, :foreign_key => :collid, :primary_key => :collid
has_many :archive_object, :through => :archive_object_collections
belongs_to :repository, :foreign_key => "repid"
end
class Repository < ActiveRecord::Base
has_many :collections
end但是,我担心切换到repository_id不会解决这个问题,因为集合表上还没有任何类型的id。这就是为什么我需要运行这个查询,这样我就可以在集合表中作为外键找到并插入该信息。我已经尝试了集合类中没有foreign_key的内部联接查询,没有进行任何更改。
很抱歉这个冗长而复杂的问题。有人有什么建议吗?谢谢!
发布于 2015-01-12 22:59:26
我决定迭代集合和存储库表,并手动匹配它。这就是我最后所做的:
class AddForeignKeyToColl < ActiveRecord::Migration
def up
# Add a repid to the collections
add_column :collections, :repository_id, :integer
# Need to go through all of the repositories
# and match their name against the repname of the collections
# Then, if they match, add the repository id to the collection as repid
repos = Repository.all
colls = Collection.all
repos.each do |repo|
rname = repo.repname
colls.each do |coll|
if coll.repname == rname
coll.update_attributes(:repository_id => repo.id)
end
end
end
end
def down
raise ActiveRecord::IrreversibleMigration
end
end好像起作用了!
发布于 2015-01-12 21:58:25
我认为您应该在存储库模型中定义foreign_key。
class Repository < ActiveRecord::Base
has_many :collections, :primay_key => 'somekey', :foreign_key => 'repid'
end然后,您可以运行一个简单的联接查询,根据查询获取一个结果。
Repository.select('repositories.*, collections.*').where("repositories.col1 = ? AND collections.col2 = ?", val1, val2)否则,如果您想摆脱这些类型的键定义,那么最好开始使用rails约定。将外键定义为model_id。在这种情况下,您不必定义键名。
https://stackoverflow.com/questions/27911150
复制相似问题