belongs_to的belongs_to的关联只是没有的has_many或HAS_ONE [英] belongs_to belongs_to association only no has_many or has_one

查看:207
本文介绍了belongs_to的belongs_to的关联只是没有的has_many或HAS_ONE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您可以在Rails中 belongs_to的 belongs_to的关系?

<一个href=\"http://stackoverflow.com/questions/18933994/can-belongs-to-work-without-has-many-or-has-one\">Search <一href=\"http://stackoverflow.com/questions/13436889/activerecord-do-i-need-both-belongs-to-and-has-one\">results给了我两个结果。我无法找到关于这个问题非常多的信息,这一事实似乎表明,它不应该做或不好的做法。

我问<一个href=\"http://stackoverflow.com/questions/32756143/rails-associations-has-many-through-ban-archive-solution\">yesterday有关的has_many关系,但认为是因为我找不到这方面的资料,我会产生一个问题,所以很容易为人们对未来搜索此。我转述其他用户的回答(我希望这是确定)。

鞋可以有很多袜子,但只有一个活跃的袜子。其他袜子无效。所有的袜子也具有独特的模式是独一无二的。我要确保我没有袜子相同的模式。我想我可以做到这三种方法

 类袜子&LT; ActiveRecord的::基地
  belongs_to的:鞋
结束

要找出是否袜子有效或无效的,给予其'主人的鞋,像这样为有效袜子的引用:

 类鞋&LT; ActiveRecord的::基地
  belongs_to的:袜子
结束

转到它的主人鞋和检查鞋子的积极袜子是当前袜子与否。例如。

 高清IS_ACTIVE
  owner_shoe.active_sock ==自我

与外键关联它们

 类CreateGettingDressed&LT; ActiveRecord的::迁移
  高清变化
    CREATE_TABLE:鞋子做| T |
      t.belongs_to:active_sock,foreign_key:sock_id
      t.string:大小
      t.timestamps空:假的
    结束    CREATE_TABLE:袜子做| T |
      t.belongs:owner_shoe,foreign_key:shoe_id
      t.string:图案
    结束
  结束
结束


解决方案

你的问题是你的功能,两片相互矛盾的:


  

A 可以有很多的袜子,但只有一个活动的袜子


您正在寻找的两款车型上的两个不同的联想关联。虽然这种做法仅仅是,我觉得你想要做的方式是在一个小的限制。

下面是我设置基准协会:

 #应用程序/模型/ sock.rb
类袜子&LT; ActiveRecord的::基地
   #columns ID | shoe_id |名称|活性(布尔值)| created_at |的updated_at
   belongs_to的:鞋
结束#应用程序/模型/ shoe.rb
一流的鞋&LT; ActiveRecord的::基地
   #columns ID |名称|等| created_at |的updated_at
   的has_many:袜子
   适用范围:积极, - &GT; {其中,(活动:真)。首先}
结束

这会给你打电话的能力:

  @shoe = Shoe.find 1
@#shoe.socks.active - &GT;先用袜子主动布尔为真

这也将否定需要包括活跃?方法在袜子模式。您可以拨打 @ shoe.socks.find(2)。主动?来得到关于它是否是主动或不响应。


现在,这个的的工作pretty以及基本功能。

不过,你提到的几个扩展:


  

如果一个袜子是有效不活跃


  
  

我要确保我没有使用相同的花纹袜


这增加了它我会用加入模型(的 的has_many:通过 ):

 #应用程序/模型/ sock.rb
类袜子&LT; ActiveRecord的::基地
   的has_many:shoe_socks
   的has_many:鞋,通过:shoe_socks
结束#应用程序/模型/ shoe_sock.rb
类ShoeSock&LT; ActiveRecord的::基地
   #列ID | shoe_id | sock_id | pattern_id |主动| created_at |的updated_at
   belongs_to的:鞋
   belongs_to的:袜子
   belongs_to的:模式
结束#应用程序/模型/ shoe.rb
一流的鞋&LT; ActiveRecord的::基地
   的has_many:shoe_socks
   的has_many:袜子,通过:shoe_socks,延长:ActiveSock
   适用范围:积极, - &GT; {其中,(活动:真)。首先}
结束

您可以阅读更多关于下面的code <一个href=\"http://stackoverflow.com/questions/21401629/accessing-parent-through-unsaved-child-association-has-many-through\">here:

 #应用程序/模型/关注/ active_sock.rb
模块ActiveSock    #加载
    高清负荷
      captions.each做|标题|
          proxy_association.target&LT;&LT;活性
      结束
    结束    #私人的
    私人的    #Captions
    高清字幕
            return_array = []
            through_collection.each_with_index做|通过,我|
                    副= through.send(reflection_name)
                    associate.assign_attributes({活跃:项目[I]})
                    return_array.concat Array.new(1).fill伪(副教授)
            结束
            return_array
    结束    #######################
    ##变量
    #######################    #协会
    高清reflection_name
            proxy_association.source_reflection.name
    结束    #Foreign关键
    高清through_source_key
            proxy_association.reflection.source_reflection.foreign_key
    结束    #首要的关键
    高清through_primary_key
              proxy_association.reflection.through_reflection.active_record_primary_key
    结束    #Through名称
    高清through_name
            proxy_association.reflection.through_reflection.name
    结束    #通过
    高清through_collection
            proxy_association.owner.send through_name
    结束    #Captions
    DEF项目
            through_collection.map(安培;:有效)
    结束    #目标
    高清target_collection
            #load_target
            proxy_association.target
    结束

此安装程序将基本上把所有的逻辑到加盟模式。 IE浏览器,你会拥有的袜子的,之一的的和带有两个连接碎料DB。

数据库

这仍然将允许你打电话 @ shoe.socks.active ,但无需降低在数据模型中的数据完整性。

我还添加了一些code,我写了一会儿回来 - 这让你从加盟模式访问属性的能力。它使用的ActiveRecord的 proxy_association 对象,因此它不会调用更多的SQL。

这增加code将追加活跃?属性任何关联袜子的对象。

Can you have a belongs_to belongs_to relationship in Rails?

Search results gave me two results. The fact that I can't find very much info on the subject, seems to indicate that it shouldn't be done or is bad practice.

I asked yesterday about a has_many relationship, but thought because I couldn't find information on this, I would generate a question so it is easier for people to search for this in the future. I'm paraphrasing another users answer (I hope this is ok).

A Shoe can have many Socks, but only one active Sock. Other Socks are inactive. All Socks are also unique with unique patterns. I want to make sure I don't have socks with the same pattern. I think I can do this three ways

class Sock < ActiveRecord::Base
  belongs_to :shoe
end

To find out if a Sock is active or inactive, give its' owner shoe a reference to its active sock like so:

class Shoe < ActiveRecord::Base
  belongs_to :sock
end

Go to its owner Shoe and check if the Shoe's active sock is the current Sock or not. E.g.

def is_active
  owner_shoe.active_sock == self

Associate them with foreign keys

class CreateGettingDressed < ActiveRecord::Migration
  def change
    create_table :shoes do |t|
      t.belongs_to :active_sock, foreign_key: "sock_id"
      t.string :size
      t.timestamps null: false
    end

    create_table :socks do |t|
      t.belongs :owner_shoe, foreign_key: "shoe_id"
      t.string :pattern
    end
  end
end

解决方案

The problem you have is your two pieces of functionality are conflicting:

A Shoe can have many Socks, but only one active Sock

You're looking to associate the two models on two different associations. Although this is simply done, I feel the way you're trying to do is is a little restricted.

Here's how I'd set up the base association:

#app/models/sock.rb
class Sock < ActiveRecord::Base
   #columns id | shoe_id | name | active (boolean) | created_at | updated_at
   belongs_to :shoe
end

#app/models/shoe.rb
class Shoe < ActiveRecord::Base
   #columns id | name | etc | created_at | updated_at
   has_many :socks
   scope :active, -> { where(active: true).first }
end

This will give you the ability to call:

@shoe = Shoe.find 1
@shoe.socks.active #-> first sock with "active" boolean as true

It will also negate the need to include an active? method in your sock model. You can call @shoe.socks.find(2).active? to get a response as to whether it's active or not.


Now, this should work pretty well for basic functionality.

However, you mention several extensions:

if a Sock is active or inactive

I want to make sure I don't have socks with the same pattern

This adds extra specifications which I'd tackle with a join model (has_many :through):

#app/models/sock.rb
class Sock < ActiveRecord::Base
   has_many :shoe_socks
   has_many :shoes, through: :shoe_socks
end

#app/models/shoe_sock.rb
class ShoeSock < ActiveRecord::Base
   # columns id | shoe_id | sock_id | pattern_id | active | created_at | updated_at
   belongs_to :shoe
   belongs_to :sock
   belongs_to :pattern
end

#app/models/shoe.rb
class Shoe < ActiveRecord::Base
   has_many :shoe_socks
   has_many :socks, through: :shoe_socks, extend: ActiveSock
   scope :active, -> { where(active: true).first }
end

You can read more about the below code here:

#app/models/concerns/active_sock.rb
module ActiveSock

    #Load
    def load
      captions.each do |caption|
          proxy_association.target << active
      end
    end

    #Private
    private

    #Captions
    def captions
            return_array = []
            through_collection.each_with_index do |through,i|
                    associate = through.send(reflection_name)
                    associate.assign_attributes({active: items[i]})
                    return_array.concat Array.new(1).fill( associate )
            end
            return_array
    end

    #######################
    #      Variables      #
    #######################

    #Association
    def reflection_name
            proxy_association.source_reflection.name
    end

    #Foreign Key
    def through_source_key
            proxy_association.reflection.source_reflection.foreign_key
    end

    #Primary Key
    def through_primary_key
              proxy_association.reflection.through_reflection.active_record_primary_key
    end

    #Through Name
    def through_name
            proxy_association.reflection.through_reflection.name
    end

    #Through
    def through_collection
            proxy_association.owner.send through_name
    end

    #Captions
    def items
            through_collection.map(&:active)
    end

    #Target
    def target_collection
            #load_target
            proxy_association.target
    end

This setup will basically put all the "logic" into the join model. IE you'll have a database of socks, one of shoes and a connecting DB with parings of both.

This will still permit you to call @shoe.socks.active but without having to degrade the data integrity in your data models.

I have also added some code I wrote a while back - which gives you the ability to access attributes from the join model. It uses the proxy_association object in ActiveRecord, so it doesn't invoke any more SQL.

This added code will append the active? attribute to any associative Sock objects.

这篇关于belongs_to的belongs_to的关联只是没有的has_many或HAS_ONE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆