# Help needed to DRY helpers and proper MVC with Ruby

**URL:** <https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592>\
**Category:** Rails\
**Created:** [July 27, 2007, 9:45pm UTC](https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592 "2007-07-27T21:45:48Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![RubyTechie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ea5d25/32.png) [@RubyTechie](https://www.ruby-forum.com/u/RubyTechie)\
**Post date:** [July 27, 2007, 9:45pm UTC](https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592/1 "2007-07-27T21:45:48Z")

</div>

Hello.

I’m still fumbling learning RoR, so I apologize in advance.

I’ve got working code, but I don’t think that it’s done properly so  
any  
help to make this more efficient and most of all, correct, would be so  
very appreciated.

In my users\_helper.rb file

def generate\_sub\_nav  
if session[:user]  
sub\_nav\_menu = []  
user = User.find(session[:user])  
for role in user.roles  
for right in role.rights  
if right.on\_menu  
sub\_nav\_menu \<\< right.id  
end  
end # for right  
end # for role  
end # if  
sub\_nav\_menu.sort!  
end # def

In my application\_helper.rb file for the layout and display

def show\_sub\_nav(rights)  
html\_out = ‘

| ’

for right in rights  
right\_array = Right.find(:all, :conditions =\> [“id = ?”, right])  
for menu in right\_array  
html\_out \<\< link\_to\_unless\_current (menu.name,  
:controller =\> menu.controller, :action =\> menu.action)  
end  
end #for right in rights

html\_out \<\< ‘

 |

’  
html\_out  
end

In my controllers (not including the user\_controller)

helper :users

There’s got to be a better, more Ruby like way to do this.

THANKS!

---

<div class="post-metadata">

**Author:** ![RubyTechie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ea5d25/32.png) [@RubyTechie](https://www.ruby-forum.com/u/RubyTechie)\
**Post date:** [July 27, 2007, 10:06pm UTC](https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592/2 "2007-07-27T22:06:49Z")

</div>

> ```
> end
> end # for right
> end # for role
> end # if
> sub_nav_menu.sort!
> 
> ```
> 
> end # def

First, you might map rights to users through roles:

class User \< ActiveDirectory::Base  
has\_many :rights, :through :roles  
end

Then you could reduce that method to:

def generate\_sub\_nav  
if session[:user] && user = User.find(session[:user])  
user.rights.select {|right| right.on\_menu}.sort  
end  
end

note that I’m returning an enumeration of Rights objects, not an  
enumeration of Right object ids

> ```
> end
> 
> ```
> 
> end #for right in rights
> 
> html\_out \<\< ‘’  
> html\_out  
> end

def show\_sub\_nav(rights)  
html\_out = ‘

| ’  
rights.each do |right|  
html\_out \<\< link\_to\_unless\_current(h(right.name),  
{:controller=\>right.controller, :action=\>right.action})  
end  
html\_out \<\< ‘ |

’  
html\_out  
end

Other things you could do include including the roles and/or rights in  
the User.find method call, limiting the rights to those with the on\_menu  
attribute, and ordering the results by right id instead of sorting the  
Rights objects.

You might also want to consider loading the User object from the  
session[:user] id in a filter instead of doing it in the helper, since  
you’re likely to want to use your User object in a variety of different  
places.

I also wonder if show\_sub\_nav really merits a helper method at all. If  
it were me, I’d just put this chunk of code in your standard layout  
wrapper.

- donald

---

<div class="post-metadata">

**Author:** ![RubyTechie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ea5d25/32.png) [@RubyTechie](https://www.ruby-forum.com/u/RubyTechie)\
**Post date:** [July 27, 2007, 11:13pm UTC](https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592/3 "2007-07-27T23:13:59Z")

</div>

Thanks so much for taking the time to work with me on this. I’m  
learning so much from user groups!

Here are a couple of things that I tried with results and questions.

I have this in my user.rb file

has\_many :roles  
has\_many :rights, :through =\> :roles

But now I get a MySQL error because it’s looking for a column that  
does not exist

Mysql::Error: #42S22Unknown column ‘roles.user\_id’

The roles table doesn’t have a user\_id field. I have roles and users  
connected through the roles\_users table.

The show\_sub\_nav is part of the menu and was put into the  
application\_helper.rb file so that it could be accessed by the entire  
application. I wasn’t able to figure out where else to put it.

I’ll keep working through the rest of your suggestions to see how I  
can create better code.

THANKS!

---

<div class="post-metadata">

**Author:** ![RubyTechie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ea5d25/32.png) [@RubyTechie](https://www.ruby-forum.com/u/RubyTechie)\
**Post date:** [July 27, 2007, 11:19pm UTC](https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592/4 "2007-07-27T23:19:00Z")

</div>

Also as an FYI, the users, roles and rights design was taken from the  
Pragmatic Programmers Rails Recipes book.

---

<div class="post-metadata">

**Author:** ![RubyTechie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ea5d25/32.png) [@RubyTechie](https://www.ruby-forum.com/u/RubyTechie)\
**Post date:** [July 27, 2007, 11:29pm UTC](https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592/5 "2007-07-27T23:29:01Z")

</div>

> Thanks so much for taking the time to work with me on this.  
> I’m learning so much from user groups!

No problem.

> Mysql::Error: #42S22Unknown column ‘roles.user\_id’
> 
> The roles table doesn’t have a user\_id field. I have roles  
> and users connected through the roles\_users table.

Oops, I’ve led you astray then. I’m actually a bit surprised what you  
have works then, I thought when you did habtm you needed to tag both  
ends of the relationship as has\_and\_belongs\_to\_many. C’e la vie,  
disregard that portion of my suggestions.

It’s perhaps worth your while to try using the :include feature of  
Base.find. Something like:

User.find(session[:user], :include=\>{:roles=\>{:rights}})

should load the user data along with its roles and rights all in one  
query. I may have the syntax wrong, this is from memory.

> The show\_sub\_nav is part of the menu and was put into the  
> application\_helper.rb file so that it could be accessed by  
> the entire application. I wasn’t able to figure out where  
> else to put it.

Most folks would use ActionView’s layout feature for this, I suspect.

- donald

---

<div class="post-metadata">

**Author:** ![RubyTechie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ea5d25/32.png) [@RubyTechie](https://www.ruby-forum.com/u/RubyTechie)\
**Post date:** [July 28, 2007, 12:01am UTC](https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592/6 "2007-07-28T00:01:08Z")

</div>

Would I incorporate this into this block here?

def generate\_sub\_nav  
if session[:user] && user =  
User.find(session[:user], :include=\>{:roles=\> :rights})  
user.rights.select {|right| right.on\_menu}.sort  
end

If so, then I get this error

undefined method `rights’ for #User:0xc966b4c

But, I also removed this line

has\_many :rights, :through =\> :roles

Basically, replaced one error with a new one.

I’m getting really lost now.

---

<div class="post-metadata">

**Author:** ![RubyTechie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ea5d25/32.png) [@RubyTechie](https://www.ruby-forum.com/u/RubyTechie)\
**Post date:** [July 27, 2007, 11:58pm UTC](https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592/7 "2007-07-27T23:58:08Z")

</div>

Would I incorporate this into this block here?

def generate\_sub\_nav  
if session[:user] && user =  
User.find(session[:user], :include=\>{:roles=\> :rights})  
user.rights.select {|right| right.on\_menu}.sort  
end

If so, then I get this error

undefined method `rights’ for #User:0xc966b4c

But, I also removed this line

has\_many :rights, :through =\> :roles

Basically, replaced one error with a new one.

I’m getting really lost now.

---

<div class="post-metadata">

**Author:** ![RubyTechie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ea5d25/32.png) [@RubyTechie](https://www.ruby-forum.com/u/RubyTechie)\
**Post date:** [July 28, 2007, 12:29am UTC](https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592/8 "2007-07-28T00:29:12Z")

</div>

Would I incorporate this into this block here?

def generate\_sub\_nav  
if session[:user] && user =  
User.find(session[:user], :include=\>{:roles=\> :rights})  
user.rights.select {|right| right.on\_menu}.sort  
end

If so, then I get this error

undefined method `rights’ for #User:0xc966b4c

But, I also removed this line

has\_many :rights, :through =\> :roles

Basically, replaced one error with a new one.

I’m getting really lost now.

---

<div class="post-metadata">

**Author:** ![RubyTechie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ea5d25/32.png) [@RubyTechie](https://www.ruby-forum.com/u/RubyTechie)\
**Post date:** [July 30, 2007, 7:27pm UTC](https://www.ruby-forum.com/t/help-needed-to-dry-helpers-and-proper-mvc-with-ruby/110592/9 "2007-07-30T19:27:19Z")

</div>

Does anyone know what needs to change? Do I need to add back in  
“:throgh” and then make changes elsewhere?

Thanks for the help!
