0

So I have a table with the following values:

--------------
| id | a | b |
--------------
|  1 | 1 | 2 |
|  2 | 3 | 4 |
|  3 | 5 | 6 |
|  4 | 7 | 8 |
--------------

How would I write a validation in rails to prevent the saving of a new record if any pairing of the two value already existsed.

Important: I'm not talking about just pairings of values for the same attributes, but both possible pairings. For instance, in the table above I should be able to save :a => 6, :b =>5 because the row 3 already contains that relationship.

Betjamin Richards
  • 1,071
  • 2
  • 12
  • 34
  • possible duplicate of [How do you validate uniqueness of a pair of ids in Ruby on Rails?](http://stackoverflow.com/questions/923796/how-do-you-validate-uniqueness-of-a-pair-of-ids-in-ruby-on-rails) – Ciro Santilli OurBigBook.com Jul 01 '14 at 15:59

1 Answers1

5

You can use scope to validate multiple uniqueness.

validates_uniqueness_of :a, scope: :b

Given [{a: 5, b: 6}, {a: 7, b: 8}] exists. For the following new values:

  1. {a: 7, b: 9} will pass
  2. {a: 7, b: 8} disallowed
  3. {a: 8, b: 7} will pass

So here comes your further question about two way uniqueness, that is you don't allow #3 data to pass.

To my knowledge I don't know a such direct validation rule.

But here is a good workaround for this case, that is, you insert two records in one transaction.

For example, originally the value you are going to save is {a: 7, b: 8}, but in this workaround, you insert both {a:7, b:8} and {a:8, b:7}.

By this way, using the above validation rule, you can effective prevent two-way duplication.

The practice has been used on friend relationship cases. For example, you are User7, I'm User8. If we become friends, two records as above must been added. By this way, when searching your friends, I'm there. And when searching my friends, you are there as well.

Billy Chan
  • 24,625
  • 4
  • 52
  • 68
  • As I said in the question (though not particularly well worded perhaps) is that this will only capture 50% of what i need. E.g. If there's a a:1 b:2 it will catch an attempt to save a:1 b:2 again but not a:2 b:1. I want to be able to capture this second pair as well – Betjamin Richards May 23 '13 at 16:27
  • thanks for the update. Would it be more economical to write a custom validator that validates the uniqueness of the record both ways around? – Betjamin Richards May 23 '13 at 17:27
  • @BetjaminRichards, I think it's possible to write such a validator. But it depends on your business logic. If such validation is important to you, two way querying must be also very useful at your business, so why not do them together? – Billy Chan May 23 '13 at 18:03
  • I'm trying to adapt the postgres graph guide here: http://techportal.inviqa.com/2009/09/07/graphs-in-the-database-sql-meets-social-networks/ . I'm working on the basis that it is non-directional graph. – Betjamin Richards May 23 '13 at 18:20