# Circular DB problem

**URL:** <https://www.ruby-forum.com/t/circular-db-problem/110851>\
**Category:** Rails\
**Created:** [July 31, 2007, 3:34pm UTC](https://www.ruby-forum.com/t/circular-db-problem/110851 "2007-07-31T15:34:40Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![simon1](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@simon1](https://www.ruby-forum.com/u/simon1)\
**Post date:** [July 31, 2007, 3:34pm UTC](https://www.ruby-forum.com/t/circular-db-problem/110851/1 "2007-07-31T15:34:40Z")

</div>

Hi,

Wondering if anybody could give me a hand. I have three tables,  
operators, operator\_aps, and pingable\_ips with the following  
relationships:

operator has\_many operator\_aps  
operator has\_many pingable\_ips

Now, what I need to do is relate one of the operator’s pingable\_ips  
with each of their operator\_aps. I’m not sure what the best way to go  
about this is, or how to properly define it with the has\_many/  
belongs\_to relationships. I was thinking of just doing:

operator\_ap has\_one pingable\_ip

but then pingable\_ip belongs\_to both operator and operator\_ap, and  
operator\_ap already belongs\_to an operator. Not sure if this will  
cause any issues, especially when deleting records from these tables.

If anybody has any advice on a nice way to set these relationships up,  
it would be greatly appreciated.

Thanks,

Simon

---

<div class="post-metadata">

**Author:** ![simon1](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@simon1](https://www.ruby-forum.com/u/simon1)\
**Post date:** [July 31, 2007, 3:56pm UTC](https://www.ruby-forum.com/t/circular-db-problem/110851/2 "2007-07-31T15:56:42Z")

</div>

On Tue, 31 Jul 2007, Simon wrote:

> Now, what I need to do is relate one of the operator’s pingable\_ips  
> with each of their operator\_aps. I’m not sure what the best way to go  
> about this is, or how to properly define it with the has\_many/  
> belongs\_to relationships. I was thinking of just doing:
> 
> operator\_ap has\_one pingable\_ip
> 
> but then pingable\_ip belongs\_to both operator and operator\_ap, and  
> operator\_ap already belongs\_to an operator. Not sure if this will  
> cause any issues, especially when deleting records from these tables.

I think it depends on the relationship between pingable\_aps and  
pingable\_ips. If you allocate the ip to the app depending on  
whether it is one of the operator’s ip addresses, then break the  
association between the operator and the app. You can always tell  
the ip address to do things to the apps it owns. Otherwise, if you  
allocate the ap depending on whether it is going to the operator’s  
app, break the association between the operator and the ip.  
Basically, they should not be poking in each other’s pockets so  
much. If it is one ip per app, you can always ask the apps to  
handle the IP issues.

As a third choice, the operator keeps the mapping between  
her apps and her ips, and the two need never know about this  
directly.

Circular graphs make recursion too … er, interesting…

> If anybody has any advice on a nice way to set these relationships up,  
> it would be greatly appreciated.
> 
> Thanks,
> 
> Simon

```
HTH, though I don't understand your problem domain in detail.
Hugh
```

---

<div class="post-metadata">

**Author:** ![simon1](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@simon1](https://www.ruby-forum.com/u/simon1)\
**Post date:** [July 31, 2007, 5:01pm UTC](https://www.ruby-forum.com/t/circular-db-problem/110851/3 "2007-07-31T17:01:09Z")

</div>

Simon wrote:

> Hi,

\> \> operator has\_many operator\_aps \> operator has\_many pingable\_ips \> \> \> operator\_ap has\_one pingable\_ip \> \> but then pingable\_ip belongs\_to both operator and operator\_ap, and \> operator\_ap already belongs\_to an operator. Not sure if this will \> cause any issues, especially when deleting records from these tables. \> \> If anybody has any advice on a nice way to set these relationships up, \> it would be greatly appreciated. \> \> Thanks, \> \> Simon

Simon! (cool to see you on this list)

If I understand you correctly, this is what you have…

class Operator \< ActiveRecord::Base  
belongs\_to :operator\_app  
has\_many :pingable\_ips  
end

class OperatorApp \< ActiveRecord::Base  
has\_many :operators  
has\_many :pingable\_ips  
end

class PingableIp \< ActiveRecord::Base  
belongs\_to :operator\_app  
belongs\_to :operator  
end

You should be fine when it comes to destroying records, the thing to  
watch for is how you set up your foreign key constraints! (Just watch  
for the caveat at the bottom.)

> > oa = OperatorApp.new  
> > =\> #\<OperatorApp:0x3466128 @new\_record=true, @attributes={}\>
> 
> > oa.operators \<\< Operator.new  
> > =\> [#\<Operator:0x3464224 @new\_record=true,  
> > @attributes={“operator\_app\_id”=\>nil}\>]
> 
> > oa.pingable\_ips \<\< PingableIp.new  
> > =\> [#\<PingableIp:0x345ec98 @new\_record=true,  
> > @attributes={“operator\_id”=\>nil, “operator\_ap\_id”=\>nil}\>]
> 
> > oa.pingable\_ips.first.operator = oa.operators.first # \<- the “circular” reference you are concerned about  
> > =\> #\<Operator:0x3464224 @new\_record=true,  
> > @attributes={“operator\_app\_id”=\>nil}\>
> 
> > oa.save  
> > =\> true
> 
> > oa.destroy  
> > =\> #\<OperatorApp:0x3466128 @errors=#\<ActiveRecord::Errors:0x3456278  
> > @errors={}, @base=#\<OperatorApp:0x3466128 …\>\>, @new\_record=false,  
> > @pingable\_ips=[#\<PingableIp:0x345ec98  
> > @errors=#\<ActiveRecord::Errors:0x3456048 @errors={},  
> > @base=#\<PingableIp:0x345ec98 …\>\>, @new\_record=false,  
> > @operator=#\<Operator:0x3464224 @errors=#\<ActiveRecord::Errors:0x3455e04  
> > @errors={}, @base=#\<Operator:0x3464224 …\>\>, @new\_record=false,  
> > @attributes={“id”=\>2, “operator\_app\_id”=\>2},  
> > @new\_record\_before\_save=true\>, @attributes={“operator\_id”=\>2, “id”=\>2,  
> > “operator\_ap\_id”=\>nil, “operator\_app\_id”=\>2}\>], @attributes={“id”=\>2},  
> > @new\_record\_before\_save=true, @operators=[#\<Operator:0x3464224  
> > @errors=#\<ActiveRecord::Errors:0x3455e04 @errors={},  
> > @base=#\<Operator:0x3464224 …\>\>, @new\_record=false,  
> > @attributes={“id”=\>2, “operator\_app\_id”=\>2},  
> > @new\_record\_before\_save=true\>]\>

> > OperatorApp.find(:all)  
> > =\> []
> 
> > Operator.find(:all)  
> > =\> [#\<Operator:0x34400cc @attributes={“id”=\>“2”,  
> > “operator\_app\_id”=\>“2”}\>]
> 
> > PingableIp.find(:all)  
> > =\> [#\<PingableIp:0x343d764 @attributes={“operator\_id”=\>“2”,  
> > “operator\_ap\_id”=\>nil, “id”=\>“2”}\>]
> 
> >

just notice the orphans with the last 2 statements and just make sure to  
clean them up in your models with the appropriate filter

hth

ilan

---

<div class="post-metadata">

**Author:** ![simon1](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@simon1](https://www.ruby-forum.com/u/simon1)\
**Post date:** [July 31, 2007, 9:43pm UTC](https://www.ruby-forum.com/t/circular-db-problem/110851/4 "2007-07-31T21:43:03Z")

</div>

Simon wrote:

> Hi,
> 
> That was close to what I meant, but here is what I was trying to get  
> at:
> 
> class Operator \< ActiveRecord::Base  
> has\_many :operator\_app  
> has\_many :pingable\_ips  
> end
> 
> class OperatorApp \< ActiveRecord::Base  
> belongs\_to :operators  
> has\_one :pingable\_ips  
> end
> 
> class PingableIp \< ActiveRecord::Base  
> belongs\_to :operator\_app  
> belongs\_to :operator  
> end
> 
> I just don’t like how those relationships are circular, with the  
> PingableIp belonging to both the Operator and the OperatorApp, when  
> the OperatorApp also belongs to an Operator. But so far I haven’t  
> come up with a clever way to handle those relationships differently.  
> Basically, the Operator has many OperatorApps and PingableIps, and  
> each single OperatorApp needs to be associated with a single  
> PingableIp that also belongs to that Operator. The same PingableIp  
> can be related to several OperatorApps.

Hi,

The API documentation states that belongs\_to is used on a model class  
when you have foreign keys on the model’s table. So what does your  
pingable\_ips table look like? The way your PingableIp class is setup now  
implies that the pingable\_ips table has a operator\_app\_id and an  
operator\_id. But the operator\_apps table would also have an  
operator\_id, so it’s actually redundant (I wouldn’t really call it  
circular).

Since you don’t need the foreign key, I believe that means you shouldn’t  
(and can’t) have the belongs\_to :operator in your PingableIp. In your  
Operator class, you can put has\_many :pingable\_ips, :through =\>  
:operator\_app.

(It’s like the Firm/Client/Invoice example in the “Association Join  
Models” section of the ActiveRecord::Assocations::ClassMethods  
documentation. See  
[ActiveRecord::Associations::ClassMethods](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html))

---

<div class="post-metadata">

**Author:** ![simon1](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@simon1](https://www.ruby-forum.com/u/simon1)\
**Post date:** [July 31, 2007, 7:34pm UTC](https://www.ruby-forum.com/t/circular-db-problem/110851/5 "2007-07-31T19:34:21Z")

</div>

Hi,

That was close to what I meant, but here is what I was trying to get  
at:

class Operator \< ActiveRecord::Base  
has\_many :operator\_app  
has\_many :pingable\_ips  
end

class OperatorApp \< ActiveRecord::Base  
belongs\_to :operators  
has\_one :pingable\_ips  
end

class PingableIp \< ActiveRecord::Base  
belongs\_to :operator\_app  
belongs\_to :operator  
end

I just don’t like how those relationships are circular, with the  
PingableIp belonging to both the Operator and the OperatorApp, when  
the OperatorApp also belongs to an Operator. But so far I haven’t  
come up with a clever way to handle those relationships differently.  
Basically, the Operator has many OperatorApps and PingableIps, and  
each single OperatorApp needs to be associated with a single  
PingableIp that also belongs to that Operator. The same PingableIp  
can be related to several OperatorApps.

Maybe I’m missing something obvious, or just thinking about the  
relationships the wrong way, but there must be a cleaner way to get  
this set up.

Thanks again,

Simon

On Jul 31, 11:01 am, Ilan B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
