# Weird stuff: validate\_uniqueness\_of with :scope does not work

**URL:** <https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577>\
**Category:** Rails\
**Created:** [September 7, 2010, 12:58pm UTC](https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577 "2010-09-07T12:58:50Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Swartz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/90db22/32.png) [@Swartz](https://www.ruby-forum.com/u/Swartz)\
**Post date:** [September 7, 2010, 12:58pm UTC](https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577/1 "2010-09-07T12:58:50Z")

</div>

Running rails 2.3.8.

I have a two models defined like this

class Member  
has\_many :folders  
before\_save: create\_default\_folders

protected  
def create\_default\_folders!  
%w{Inbox Sent}.each do |folder|  
unless self.folders.find\_by\_name(folder)  
self.folders.create!(:name =\> folder, :deletable =\> false)  
end  
end  
end  
end

class Folder  
belongs\_to :member

# folder names must be unique for each user

validates\_uniqueness\_of :name, :scope =\> [:member\_id], :allow\_blank  
=\> false,  
:case\_sensitive =\> false, :message =\> ‘already exists for this  
member’  
end

------ MembersController  
def create  
@member = Member.new(params[:member])

```
if @member.save
     ...
end

```

end

So as you can see, what I wish to get when I save a new Member are two  
default folders colled (Inbox and Sent).  
So I defined the after\_save callback. I tested it in script/console  
and it works whenever I build and save a Member.

However, as soon as I create a member through a controller-backed  
form, the uniqueness validation gets tripped up. I get validation  
error from my validates\_uniqueness\_of as “Folder already exists for  
this member”. Which shouldn’t happen.

For some strange reason :scope gets ignored and thus uniqueness check  
isn’t properly scoped by member\_id…

The weird part is that it all works in script/console, but not via web  
forms.

Any suggestions???

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![Swartz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/90db22/32.png) [@Swartz](https://www.ruby-forum.com/u/Swartz)\
**Post date:** [September 7, 2010, 1:35pm UTC](https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577/2 "2010-09-07T13:35:43Z")

</div>

On Sep 7, 11:55 am, Swartz [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 

Is there some odd interaction because you’re creating these folders  
from a before\_save (ie the member’s id has not yet been set)?

Fred

---

<div class="post-metadata">

**Author:** ![Swartz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/90db22/32.png) [@Swartz](https://www.ruby-forum.com/u/Swartz)\
**Post date:** [September 7, 2010, 4:34pm UTC](https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577/3 "2010-09-07T16:34:54Z")

</div>

dont use the before\_save use transactions that way it will roll back  
both  
actions if there is an error.  
and dont use that function you have with the each and all use

find\_or\_create\_by\_name(name)

it does what you want.

On Tue, Sep 7, 2010 at 7:20 AM, Frederick C.  
\<removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![Swartz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/90db22/32.png) [@Swartz](https://www.ruby-forum.com/u/Swartz)\
**Post date:** [September 7, 2010, 7:39pm UTC](https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577/4 "2010-09-07T19:39:56Z")

</div>

That’s what I thought originally about id not being set… but why  
does it work from script/console ?  
That kind of puzzles me…

On Sep 7, 5:20 am, Frederick C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> On Sep 7, 11:55 am, Swartz [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

---

<div class="post-metadata">

**Author:** ![Swartz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/90db22/32.png) [@Swartz](https://www.ruby-forum.com/u/Swartz)\
**Post date:** [September 7, 2010, 8:10pm UTC](https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577/5 "2010-09-07T20:10:23Z")

</div>

Also note that I have to set at least one other folder attribute while  
creating a folder ,  
so this variant doesn’t help me much.

---

<div class="post-metadata">

**Author:** ![Swartz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/90db22/32.png) [@Swartz](https://www.ruby-forum.com/u/Swartz)\
**Post date:** [September 7, 2010, 7:38pm UTC](https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577/6 "2010-09-07T19:38:46Z")

</div>

That code must’ve been 5th iteration of trying to get that call back  
to work.

I’ve tried your suggested method.  
I’ve so tried create/create!, save/save!.

Everything work from console.  
That is I can do  
m = Member.new  
m.x = “value”  
m.folders.find\_or\_create\_by\_name('folder\_name")  
m.save

It all work beautifully from console. I can test my validation, it  
works.

But as soon as I do the same thing (create new Member) from controller  
context via form params, the scoped validates\_uniqueness\_of does not  
function as expected.

–  
Swartz

---

<div class="post-metadata">

**Author:** ![Swartz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/90db22/32.png) [@Swartz](https://www.ruby-forum.com/u/Swartz)\
**Post date:** [September 9, 2010, 2:08am UTC](https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577/7 "2010-09-09T02:08:48Z")

</div>

I’ve created a brand new Rails 2.3.8 app.  
No gems, nothing.

I created only the bare necessities:  
Two models (Member and Folder)  
one controller (MembersController with only new and create actions)  
one view (new).

I can create one member with default folders as per my callback (the  
very first one), but any subsequent members don’t get default folders  
created for them.

But again, when I try the same thing from script/console everything  
works (I create new member and, bam, two folders come into existence  
as well)…

w t f…

---

<div class="post-metadata">

**Author:** ![Swartz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/90db22/32.png) [@Swartz](https://www.ruby-forum.com/u/Swartz)\
**Post date:** [September 9, 2010, 4:58am UTC](https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577/8 "2010-09-09T04:58:33Z")

</div>

watch this and see if ti helps,

> **[\#196 Nested Model Form Part 1 - RailsCasts](http://railscasts.com/episodes/196-nested-model-form-part-1)**
>
> Short Ruby on Rails screencasts containing tips, tricks and tutorials. Great for both novice and experienced web developers.

---

<div class="post-metadata">

**Author:** ![Swartz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/90db22/32.png) [@Swartz](https://www.ruby-forum.com/u/Swartz)\
**Post date:** [September 7, 2010, 11:32pm UTC](https://www.ruby-forum.com/t/weird-stuff-validate-uniqueness-of-with-scope-does-not-work/194577/9 "2010-09-07T23:32:55Z")

</div>

check your attri\_accesible, and check if you rae using a gem that uses  
attr\_protected, it appears you have a problem with mass assignment and  
you  
cant see from one controller the attribute that member\_id from the  
folder  
controller i think you need to be able to , also note that with before  
save  
there is no member\_id in the database to compare the validation with  
thats  
why i said you should use a transaction and create everything from the  
member controller like this

Member.transaction do  
@member.new(blah, blah)  
@member.save!  
params[:folder\_name].nil? ? name= “Default” : name =  
params[:folder\_name]  
@folder = Folder.find(:conditions =\>{:name = name, :member\_id=\>  
@member.id})

@folder ||= Folder.new(blah blah)  
@folder.member = @member  
@folder.save!  
end

try that, the code inside the transaction will rollback if either to the  
save fail and everything will go back to the its original state.
