# We don't need no stinking Badges! Guidance, anyone?

**URL:** <https://www.ruby-forum.com/t/we-dont-need-no-stinking-badges-guidance-anyone/159468>\
**Category:** Rails\
**Created:** [February 4, 2009, 8:37pm UTC](https://www.ruby-forum.com/t/we-dont-need-no-stinking-badges-guidance-anyone/159468 "2009-02-04T20:37:46Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ldenman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/9e8a1a/32.png) [@ldenman](https://www.ruby-forum.com/u/ldenman)\
**Post date:** [February 4, 2009, 8:37pm UTC](https://www.ruby-forum.com/t/we-dont-need-no-stinking-badges-guidance-anyone/159468/1 "2009-02-04T20:37:46Z")

</div>

Hi, Thanks for taking a look at this. I am in need of some guidance for  
a particular problem:

My Requirements:  
The concept of a user  
The concept of a badge

A badge is simply a small image over the user’s avatar that displays  
extra information about the user.  
An admin user will be able to assign a badge to any user and the  
assigned badge will become the user’s current badge, displayed for all  
the world to see.

Not required for now but required in the future: a user will be able to  
choose from a list of badges and create their own custom badges.

The Way of the Lost:

After toying with these requirements and bits of code for a few days, I  
have decided to ask for help.  
Please enlighten me on a better, a more rails way of implementing this.  
I am truly curious to know. There MUST be a better way!

RELATIONSHIPS:

I decided to implement the requirements by using a HasManyThrough  
association.  
I have three classes that collaborate: User, Badge, UserBadge

class User \< ActiveRecord::Base  
has\_many :user\_badges  
has\_many :badges, :through =\> :user\_badges  
has\_one :current\_badge, :class\_name =\> “UserBadge”, :conditions =\>  
{ :current =\> true }  
end

class Badge \< ActiveRecord::Base  
# t.string :title  
# t.string :image\_file\_name  
# t.string :image\_content\_type  
# t.integer :image\_file\_size  
# t.datetime :image\_updated\_at  
# t.timestamps

```
has_many :user_badges
has_many :users, :through => :user_badges

```

end

class UserBadge \< ActiveRecord::Base

```
# t.integer :user_id
# t.integer :badge_id
# t.boolean :current, :default => false
# t.timestamps

belongs_to :user
belongs_to :badge

```

end

ASSIGNING A CURRENT BADGE:

I need a way to assign a badge to a user, so I created an attr\_accessor  
in the User class called :assign\_current\_badge  
Then, I override the assign\_current\_badge setter method.

The assign\_current\_badge=(badge\_id) method:

- accepts a badge\_id as a formal parameter
- updates any other current user\_badges to “current=false” with the  
deactivate\_badges method
- checks for existance of a user\_badge with the user’s id and badge\_id
  - setting the user\_badge.current to true if it exists
  - creating and setting the user\_badge.current to true if it does not  
exist

- sets the user’s current\_badge\_id to the badge\_id

class User \< ActiveRecord::Base  
… # relationships

attr\_accessor :assign\_current\_badge

def assign\_current\_badge=(badge\_id)  
deactivate\_badges  
if UserBadge.exists?(:user\_id =\> id, :badge\_id =\> badge\_id)  
user\_badges.find\_by\_badge\_id(badge\_id).update\_attribute(:current,  
true)  
else  
user\_badges.create!(:badge =\> Badge.find(badge\_id), :current =\>  
true)  
end  
self.current\_badge\_id = badge\_id  
end

def deactivate\_badges  
user\_badges.update\_all(“current = 0”)  
end  
end

PROBLEMS I HAVE ENCOUNTERED:

The main problem I encounter is setting the current badge to a blank  
value through the user’s edit form.  
“Couldn’t find Badge with ID=” is being raised since there really is  
no badge with a blank id.  
This tells me, obviously, that there is a better way to go about this.  
My gut tells me there is something shady about passing in the badge\_id  
instead of an existing badge object.

- form\_for @user, :url =\> admin\_user\_path(@user) do |f|  
= f.error\_message
# … more fields
%div  
= f.label :assign\_current\_badge  
= f.select :assign\_current\_badge, Badge.all.map {|b| [b.title, b.id]}, { :selected =\> @user.current\_badge\_id, :include\_blank =\> true }
# … submit button

Finale:  
If you have any advice for me, please reply. Hopefully I explained my  
situation well enough through code and writing. If you would like me to  
elaborate on anything, just ask.

---

<div class="post-metadata">

**Author:** ![ldenman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/9e8a1a/32.png) [@ldenman](https://www.ruby-forum.com/u/ldenman)\
**Post date:** [February 5, 2009, 1:02am UTC](https://www.ruby-forum.com/t/we-dont-need-no-stinking-badges-guidance-anyone/159468/2 "2009-02-05T01:02:55Z")

</div>

Could you explain your problem more clearly? The rest was beautiful.

Blog: [http://random8.zenunit.com/](http://random8.zenunit.com/)  
Learn rails: [http://sensei.zenunit.com/](http://sensei.zenunit.com/)

On 05/02/2009, at 6:37 AM, Lake D. \<rails-mailing-list@andreas-

---

<div class="post-metadata">

**Author:** ![ldenman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/9e8a1a/32.png) [@ldenman](https://www.ruby-forum.com/u/ldenman)\
**Post date:** [February 5, 2009, 3:34am UTC](https://www.ruby-forum.com/t/we-dont-need-no-stinking-badges-guidance-anyone/159468/3 "2009-02-05T03:34:27Z")

</div>

Why do you even need a UserBadge model?

I would have User model, a Badge model, where the relationship is User  
belongs\_to :badge, and badge has\_many :users.

Then you can simply assign it with some\_user.badge = some\_badge. It  
seems like you’re adding complexity with the UserBadge model and the  
current attribute.

Maybe I’m missing something but looks like, from the requirements  
you’ve outlined, you can drop that model altogether, and keep your  
design simple…

-H

On Feb 4, 2:37 pm, Lake D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
