【问题标题】:Rails has_and_belongs_to_many always inserts into databaseRails has_and_belongs_to_many 总是插入数据库
【发布时间】:2011-12-14 11:22:58
【问题描述】:

这是我的问题:

class Facility < ActiveRecord::Base
...
has_and_belongs_to_many :languages, :autosave => false, :join_table => 'facilities_languages'
... 
end

当我做这样的事情时:

facility = Facility.find(1)
language = Language.find(1)
facility.languages << language

Rails 总是执行 SQL 请求:

"INSERT INTO `facilities_languages` (`language_id`,`facility_id`) VALUES (1, 1)"

除非我调用“facility.save”,否则有没有办法避免数据库请求?

显然,这里的 :autosave 选项还有其他作用。

【问题讨论】:

  • 你想在这里用facility.languages &lt;&lt; language 行做什么?

标签: ruby-on-rails database activerecord has-and-belongs-to-many


【解决方案1】:

您的问题是您使用has_and_belongs_to_many,它不是基于Model,因此您无法将其作为对象访问。您可以创建一个正在执行关联的Model,然后您可以创建此关联模型的新对象。例如:

rails g scaffold JoinClass faculty_id:integer language_id:integer

在模型中

class JoinClass < ActiveRecord::Base
     belongs_to :faculty
     belongs_to :language
end

在其他型号中:

教师

class Faculty < ActiveRecord::Base
     has_many :join_classes
     has_many :languages, :though => :join_classes
end

语言

class Language < ActiveRecord::Base
     has_many :join_classes
     has_many :faculties, :through => :join_classes
end

然后您将能够通过创建非自动保存的关联对象来添加关联。例如,您有一个包含 ids 的 String,其中包含应该关联的语言对象的 id,在 FacultyController 中称为 language_ids

language_ids.split(",").each do |language_id|
    JoinClass.create(:faculty_id => @faculty.id, :language_id => language_id)
end

当然,这段代码应该在保存教师之后进行调整和定位。

【讨论】:

    【解决方案2】:

    如果使用铲子操作符

    来自文档 http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

    集合

    将一个或多个对象添加到集合中 在连接表中创建关联(collection.push 和 collection.concat 是此方法的别名)。请注意,这 操作立即触发更新 sql 而无需等待保存或 更新父对象的调用。

    【讨论】:

    • 如果我使用 = 或 += 也会发生这种情况。 facility.languages = [Language.find(3)] >>DELETE FROM facilities_languages WHERE facilities_languages.facility_id = 1 AND facilities_languages.language_id IN (1, 2) >>INSERT INTO facilities_languages (language_id, facility_id) 值 (3, 1)
    【解决方案3】:

    facility.languages = [语言]

    【讨论】:

    • 或 facility.languages += [language] 或任何其他数组运算符。试过了,还是发送数据库查询。
    猜你喜欢
    • 2011-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    相关资源
    最近更新 更多