在has_many上设置inverse_of:通过rails 4.1

时间:2014-09-26 06:27:20

标签: ruby-on-rails ruby-on-rails-4

文档暗示inverse_of将适用于除多态关联之外的所有内容。 http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses

然而看起来,反向仍然不适用于has_many:通过

e.g。我在以下示例中尝试使用inverse_of的每个组合都不起作用

class Event  < ActiveRecord::Base
  has_many :attendances
  has_many :users, through: :attendance
class User < ActiveRecord::Base
  has_many :attendances 
  has_many :events, through: :attendances
class Attendance < ActiveRecord::Base
  belongs_to :event
  belongs_to :user 

任何想法应该有效吗?如果是这样,我将如何设置此示例中的inverse_of?

更新

e.g。我试过的东西(也尝试过has_many:通过)

class Event  < ActiveRecord::Base
  has_many :attendances , :inverse_of => :event
  has_many :users, through: :attendance
end
class User < ActiveRecord::Base
  has_many :attendances , :inverse_of => :user
  has_many :events, through: :attendances
end
class Attendance < ActiveRecord::Base
  belongs_to :event, :inverse_of => :attendances
  belongs_to :user,  :inverse_of => :attendances
end

也尝试了

class Event  < ActiveRecord::Base
  has_many :attendances  
  has_many :users, through: :attendance , :inverse_of => :events
end
class User < ActiveRecord::Base
  has_many :attendances 
  has_many :events, through: :attendances ,:inverse_of => :users
end
class Attendance < ActiveRecord::Base
  belongs_to :event
  belongs_to :user
end

4 个答案:

答案 0 :(得分:12)

我在rails 4.1.6中遇到了同样的问题(那是我如何偶然发现这个问题)。

尝试了一些试验和错误(以及服务器重启),但以下内容对我有用:

class User < ActiveRecord::Base
  has_many :company_users
  has_many :companies, through: :company_users
end

class Company < ActiveRecord::Base
  has_many :company_users
  has_many :users, through: :company_users
end

class CompanyUser < ActiveRecord::Base
  belongs_to :company, inverse_of: :company_users
  belongs_to :user, inverse_of: :company_users
end

为清晰起见:

Schema

示例:

user = User.last
company = user.companies.build( ... )
company.save
# ...
# SQL (0.9ms)  INSERT INTO "public"."company_users" ("company_id", "created_at", "updated_at", "user_id") VALUES ($1, $2, $3, $4) RETURNING "id"  [["company_id", 4], ["created_at", "2014-10-03 03:40:58.836975"], ["updated_at", "2014-10-03 03:40:58.836975"], ["user_id", 1]]
(1.6ms)  COMMIT
CompanyUser.last
<CompanyUser:0x00000020339710> {
        :id => 4,
:company_id => 4,
   :user_id => 1,
:created_at => Thu, 02 Oct 2014 20:40:58 PDT -07:00,
:updated_at => Thu, 02 Oct 2014 20:40:58 PDT -07:00
}

所以基本上我只在连接模型中设置inverse_of

答案 1 :(得分:2)

使用:through时,guides表示不支持inverse_of。具体做法是:


inverse_of支持有一些限制:

  • 他们不使用:通过协会。
  • 他们不兼容:多态关联。
  • 他们不合作:作为协会。
  • 对于belongs_to关联,忽略has_many反向关联。

答案 2 :(得分:1)

只要不使用class_name或foreign_key,自Rails 4.1起,inverse_of会自动设置。在本视频的最后一部分中,关于设置Rails 5模型,有一个示例说明has_many关系如何在没有,然后使用inverse_of。编写一个RSpec测试,首先表明object_ids是不同的,然后在添加inverse_of之后它们最终相同:

https://www.youtube.com/watch?v=5sfufoY59Ek&feature=youtu.be&t=42m54s

答案 3 :(得分:0)

如果您只是通过关联使用,请执行

class Event  < ActiveRecord::Base
  has_many :attendances
  has_many :users, through: :attendances ## there must be  plural too
class User < ActiveRecord::Base
  has_many :attendances 
  has_many :events, through: :attendances
class Attendance < ActiveRecord::Base
  belongs_to :event
  belongs_to :user

然后EventUser将按Attendance模型(由event_iduser_idattendances表中的数据库中相互搜索。要查看详细信息,请参阅rails assocation explian

如果你想使用inverse_of关联,这意味着关系会自己绑定而不是第三方。首先你可以做到:

class Event  < ActiveRecord::Base
  has_many :attendances
  has_many :users, :inverse_of => :events
class User < ActiveRecord::Base
  has_many :attendances 
  has_many :events, :inverse_of => :users
class Attendance < ActiveRecord::Base
  belongs_to :event
  belongs_to :user

然后您需要更改您的迁移文件:

creata_table :events do |t|
  ....
  t.string, :user_id
end

creata_table :users do |t|
  ....
  t.string, :event_id
end

@event.users一样,用户模型中的user_id会直接搜索用户,但不能通过出勤模式搜索用户。

BTW,through不能与inverse_of一起使用,Rails指南已经删除它。