# Help on drying code

**URL:** <https://www.ruby-forum.com/t/help-on-drying-code/122593>\
**Category:** Rails\
**Created:** [December 9, 2007, 11:15pm UTC](https://www.ruby-forum.com/t/help-on-drying-code/122593 "2007-12-09T23:15:09Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [December 9, 2007, 11:15pm UTC](https://www.ruby-forum.com/t/help-on-drying-code/122593/1 "2007-12-09T23:15:09Z")

</div>

Hi all,

Currently I’m having to do this:

def self.authorized\_roles(controller, action)  
specific = self.find\_by\_controller\_and\_action(controller, action)  
all\_actions = self.find\_by\_controller\_and\_action(controller, ‘_’)  
all\_controllers = self.find\_by\_controller(’_’)  
role\_ids = []  
specific.each do |role\_item|  
role\_ids \<\< role\_item.role\_id  
end  
all\_actions.each do |role\_item|  
role\_ids \<\< role\_item.role\_id  
end  
all\_controllers.each do |role\_item|  
role\_ids \<\< role\_item.role\_id  
end  
role\_ids.flatten.uniq  
end

which of course is not DRY at all.

I could not find how to merge class instances (specific, all\_actions  
and all\_controllers) or how to make only one find to use the selection  
statements above (at least not in a easy to read way)

It would be better if I could do something like:

def self.authorized\_roles(controller, action)  
specific = self.find\_by\_controller\_and\_action(controller, action)  
all\_actions = self.find\_by\_controller\_and\_action(controller, ‘_’)  
all\_controllers = self.find\_by\_controller(’_’)  
#  
# MAGIC  
#  
role\_ids = []  
role\_items do |role\_item|  
role\_ids \<\< role\_item.role\_id  
end  
role\_ids.flatten.uniq  
end

Thanks!

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [December 9, 2007, 11:33pm UTC](https://www.ruby-forum.com/t/help-on-drying-code/122593/2 "2007-12-09T23:33:37Z")

</div>

Hi there,  
I don’t know if this will fulfill your needs, but maybe you could try  
this:

def self.authorized\_roles(controller, action)  
specific = self.find\_by\_controller\_and\_action(controller, action)  
all\_actions = self.find\_by\_controller\_and\_action(controller, ‘_’)  
all\_controllers = self.find\_by\_controller(’_’)  
role\_items = specific \<\< all\_actions \<\< all\_controllers  
role\_ids = []  
role\_items.each do |role\_item|  
role\_ids \<\< role\_item.role\_id  
end  
role\_ids.flatten.uniq  
end

Best,  
kodama

removed\_email\_address@domain.invalid wrote:

> Hi all,
> 
> Currently I’m having to do this:
> 
> def self.authorized\_roles(controller, action)  
> specific = self.find\_by\_controller\_and\_action(controller, action)  
> all\_actions = self.find\_by\_controller\_and\_action(controller, ‘_’)  
> all\_controllers = self.find\_by\_controller(’_’)  
> role\_ids = []  
> specific.each do |role\_item|  
> role\_ids \<\< role\_item.role\_id  
> end  
> all\_actions.each do |role\_item|  
> role\_ids \<\< role\_item.role\_id  
> end  
> all\_controllers.each do |role\_item|  
> role\_ids \<\< role\_item.role\_id  
> end  
> role\_ids.flatten.uniq  
> end
> 
> which of course is not DRY at all.
> 
> I could not find how to merge class instances (specific, all\_actions  
> and all\_controllers) or how to make only one find to use the selection  
> statements above (at least not in a easy to read way)
> 
> It would be better if I could do something like:
> 
> def self.authorized\_roles(controller, action)  
> specific = self.find\_by\_controller\_and\_action(controller, action)  
> all\_actions = self.find\_by\_controller\_and\_action(controller, ‘_’)  
> all\_controllers = self.find\_by\_controller(’_’)  
> #  
> # MAGIC  
> #  
> role\_ids = []  
> role\_items do |role\_item|  
> role\_ids \<\< role\_item.role\_id  
> end  
> role\_ids.flatten.uniq  
> end
> 
> Thanks!

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [December 9, 2007, 11:45pm UTC](https://www.ruby-forum.com/t/help-on-drying-code/122593/3 "2007-12-09T23:45:33Z")

</div>

Thanks for your fast response.

Unfortunately, it does not work for instances that contain only one  
object.

If self.find\_by\_controller\_and\_action(…) returns only one object,  
then it does not have the method \<\<.

(s and ri are RoleItems here)

> > s \<\< ri  
> > NoMethodError: undefined method `\<\<’ for #RoleItem:0x34b3a04

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [December 10, 2007, 12:15am UTC](https://www.ruby-forum.com/t/help-on-drying-code/122593/4 "2007-12-10T00:15:25Z")

</div>

I should have had that find\_all there since the beginning…

Anyway, the new code, a little more DRY is

def self.authorized\_roles(controller, action)  
role\_items = self.find\_all\_by\_controller\_and\_action(controller,  
action)  
role\_items \<\< self.find\_all\_by\_controller\_and\_action(controller,  
‘_’)  
role\_items \<\< self.find\_all\_by\_controller(’_’)  
role\_ids = []  
begin  
role\_items.flatten.each do |role\_item|  
role\_ids \<\< role\_item.role\_id  
end  
rescue  
nil  
end  
role\_ids.uniq  
end

I had to add that flatten on role\_items.each, because it would not  
work otherwise.

Thanks a lot!

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [December 9, 2007, 11:47pm UTC](https://www.ruby-forum.com/t/help-on-drying-code/122593/5 "2007-12-09T23:47:18Z")

</div>

Then do find\_all\_by\_controller\_and\_action then?

---------- Forwarded message ----------  
From: removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Date: Dec 10, 2007 9:15 AM  
Subject: [Rails] Re: Help on drying code  
To: “Ruby on Rails: Talk” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

Thanks for your fast response.

Unfortunately, it does not work for instances that contain only one  
object.

If self.find\_by\_controller\_and\_action(…) returns only one object,  
then it does not have the method \<\<.

(s and ri are RoleItems here)

> > s \<\< ri  
> > NoMethodError: undefined method `\<\<’ for #RoleItem:0x34b3a04

On Dec 9, 2:33 pm, Old E. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> role_items.each do |role_item|
> 
> ```
> 
> removed\_email\_address@domain.invalid wrote:
> 
> > ```
> > role_ids << role_item.role_id
> > 
> > ```
> > 
> > which of course is not DRY at all.  
> > all\_controllers = self.find\_by\_controller(‘\*’)  
> > Thanks!
> 
> –  
> Posted viahttp://www.ruby-forum.com/.

–  
Ryan B.

> **[frozenplague.net](http://www.frozenplague.net)**
>
> This domain may be for sale!
