# Dry dry dry

**URL:** <https://www.ruby-forum.com/t/dry-dry-dry/101320>\
**Category:** Rails\
**Created:** [August 4, 2006, 8:13am UTC](https://www.ruby-forum.com/t/dry-dry-dry/101320 "2006-08-04T08:13:19Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![imixaly4](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/3ab097/32.png) [@imixaly4](https://www.ruby-forum.com/u/imixaly4)\
**Post date:** [August 4, 2006, 8:13am UTC](https://www.ruby-forum.com/t/dry-dry-dry/101320/1 "2006-08-04T08:13:19Z")

</div>

Hello everyone!  
Ive been on rails for the last month or so and really enjoyed this  
framework.  
However its very hard to find documentation on how to do things right!

For example every beginner after a while realizes that having similar  
CRUD actions in every controller and views for them is not DRY at all!

Few days ago I found [http://dereksivers.com/rails-shared-controller.html](http://dereksivers.com/rails-shared-controller.html)  
I quite like his generic controller, not Nub class though !  
And I’ve adopted it for my project as:

controllers/basic\_crud\_controller.rb  
…  
class BasicCRUDController \< ApplicationController  
ITEMS\_PER\_PAGE = 15  
before\_filter :initialize\_crud\_controller  
verify :method =\> :post, :only =\> [:destroy, :create, :update],  
:redirect\_to =\> { :action =\> :list }  
def index  
list  
end  
def list  
@items = model\_class.find :all, :limit =\> ITEMS\_PER\_PAGE,  
:offset =\> ITEMS\_PER\_PAGE \* (@sess[:page] -  
1)  
@pages = Paginator.new self, model\_class.count, ITEMS\_PER\_PAGE,  
@sess[:page]  
render ‘shared/list’  
end  
def new  
@item = model\_class.new  
#@editform = model\_class.editform  
render ‘shared/new’  
end  
def edit  
@item = model\_class.find(params[:id])  
#@editform = model\_class.editform  
render ‘shared/edit’  
end  
def create  
@item = model\_class.new(params[:edit])  
if @item.save  
#flash[:notice] = ‘Region was successfully created.’  
flash[:notice] = sprintf(\_(:added),  
_(model\_class.table\_name.to\_sym))  
redirect\_to :action =\> :list  
else  
#@editform = model\_class.editform  
render ‘shared/new’  
end  
end  
def update  
 @item = model\_class.find(params[:id])  
if @item.update\_attributes(params[:edit])  
 #flash[:notice] = ‘Region was successfully updated.’  
flash[:notice] = sprintf(_(:updated),  
_(model\_class.table\_name.to\_sym))  
redirect\_to :action =\> :list #:edit, :id =\> @region  
else  
#@editform = model\_class.editform  
render ‘shared/edit’  
end  
end  
def destroy  
model\_class.find(params[:id]).destroy  
flash[:notice] = sprintf(_(:deleted),  
\_(model\_class.table\_name.to\_sym))  
redirect\_to :action =\> :list  
end  
private  
def initialize\_crud\_controller  
id = self.object\_id  
session[id] = { :page =\> 1 } unless session[id]  
@sess = session[id]  
@model\_name = model\_class.table\_name.singularize  
end  
end  
…

By the way, is this a good way to go?  
Should something like this be generated when you generate scaffold?  
I believe it should!

Then our custom controller looks like this:

controller/regions\_controller.rb  
…  
class RegionsController \< BasicCRUDController  
def model\_class  
Region  
end  
end  
…

Looks very DRY to me!

Now I would like to DRY the views as well  
Its very easy with list:

views/shared/list.rhtml  
…

# Listing \<%= @model\_name.pluralize %\>
\<%= link\_to 'New ' + @model\_name, :action =\> :new %\> \<%= link\_to 'Previous Page', { :page =\> @pages.current.previous } if @pages.current.previous %\> \<%= pagination\_links(@pages) %\> \<%= link\_to 'Next Page', { :page =\> @pages.current.next } if @pages.current.next %\> \<% for column in controller.model\_class.content\_columns %\> \<% end %\> 

\<% for item in @items %\>

 \<%= render :partial =\> 'list', :locals =\> { :item =\> item } %\> \<% end %\>

| \<%= column.human\_name %\> |
| --- |
| \<%= link\_to 'Edit', :action =\> :edit, :id =\> item %\> | \<%= link\_to 'Destroy', { :action =\> :destroy, :id =\> item }, :confirm =\> "Delete #{@model\_name}: #{item.name} ?", :post =\> true %\> |

...

And the custom view for list item:

views/region/\_list.rhtml  
…

\<%= item.name %\> ...

Thats looks promising?  
But there always will be but!  
The new/edit templates seem not working so far

Consider this:

views/shared/new.rhtml  
…

# New \<%= @model\_name %\>
\<%= start\_form\_tag :action =\> :create %\> \<%= render :partial =\> 'shared/form' %\> \<%= submit\_tag 'Create' %\> \<%= end\_form\_tag %\> \<%= link\_to 'Back', :action =\> :list %\> ...

views/shared/\_form.rhtml  
…  
\<%= error\_messages\_for @model\_name.to\_sym %\>

\<%= render :partial =\> ‘edit’ %\>

…

views/region/\_edit.rhtml  
…

Name  
 \<%= text\_field :region, :name %\>

...

This way of doing thigs seems to be the right one.  
So if anyone will get this last bit (new/edit) to work please let me  
know!

I would appreciate any help and suggestions!  
Thanks!

---

<div class="post-metadata">

**Author:** ![imixaly4](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/3ab097/32.png) [@imixaly4](https://www.ruby-forum.com/u/imixaly4)\
**Post date:** [August 4, 2006, 8:31am UTC](https://www.ruby-forum.com/t/dry-dry-dry/101320/2 "2006-08-04T08:31:49Z")

</div>

Hi. A few thoughts…

It’s okay to “repeat yourself” across multiple controllers. In my mind,  
controllers should be fairly short.

I’ve been where you are – a lot of controllers look similar, so it’s  
tempting to combine actions with a little bit of meta magic. But I  
advise against it. You never know when you’ll need to do something  
specific in one or more actions.

With regards to being DRY… the principle’s core message is that every  
piece of information in a system should have a single, authorative  
source or representation. (A hash (dictionary) of real estate terms and  
the database columns they map to, for example.)

The Pragmatic Programmers never intended for you to NEVER repeat  
yourself. It’s okay to say something twice. Just make sure that when  
it’s said, it’s acting under the influence of that single source.

Cheers,

- Daniel

---

<div class="post-metadata">

**Author:** ![imixaly4](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/3ab097/32.png) [@imixaly4](https://www.ruby-forum.com/u/imixaly4)\
**Post date:** [August 4, 2006, 11:38am UTC](https://www.ruby-forum.com/t/dry-dry-dry/101320/3 "2006-08-04T11:38:07Z")

</div>

Hi Daniel

The king of design I was describing above is that what I need right now.  
Just simple operations with DB and common design. And I believe many  
other developers are doing the same thing. Besides if I would want  
something different I always can owerride the DEFAULT behaviour. Isn’t  
that one of the RoR main principle? Abstraction, metaprogramming, rails,  
ruby, less code, easy?  
Anyway its just my opinion.

And its not just controllers. The templates are big and cluttered with  
all sorts of mess. And what if views should look same. Ok. You have 50  
different controllers that should look exactly same. This is the main  
thing!

So could you please explain what disadvantaget of this approach you see?

Thanks for your thoughts

---

<div class="post-metadata">

**Author:** ![imixaly4](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/3ab097/32.png) [@imixaly4](https://www.ruby-forum.com/u/imixaly4)\
**Post date:** [August 4, 2006, 1:06pm UTC](https://www.ruby-forum.com/t/dry-dry-dry/101320/4 "2006-08-04T13:06:09Z")

</div>

There is nothing wrong with taking this approach Igor if it meets your  
needs. It is more DRY that way. I think Daniel was just saying that  
often you need to tweak this or that in the controller methods so you  
end up overriding a fair amount losing many of the benefits. Also  
another reason it is used less common is that it might be easier to  
visualize what is going on in a controller when you see all the  
methods in one place, much more difficult when split across files.  
Might not be an issue for you especially if you use mostly the same  
code everywhere.

Justin Ghetland and Stuart Halloway’s Streamlined generator takes this  
approach currently, so you are not the only one thinking along these  
lines.

I find it to be an interesting idea myself, one which I am going to  
experiment around with too. It certainly would be more DRY if you  
don’t have to override that often.

Blessings,

Jeff B.  
MasterView Template Engine Developer  
[http://masterview.org/](http://masterview.org/)

---

<div class="post-metadata">

**Author:** ![imixaly4](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/3ab097/32.png) [@imixaly4](https://www.ruby-forum.com/u/imixaly4)\
**Post date:** [August 4, 2006, 8:38pm UTC](https://www.ruby-forum.com/t/dry-dry-dry/101320/5 "2006-08-04T20:38:16Z")

</div>

Igor Su wrote:

> And its not just controllers. The templates are big and cluttered with  
> all sorts of mess. And what if views should look same. Ok. You have 50  
> different controllers that should look exactly same. This is the main  
> thing!

If you feel combining controllers and views makes sense then do it.

Igor Su wrote:

> So could you please explain what disadvantaget of this approach you see?

Like Jeff said, I think the primary disadvantage is a lack of  
flexibility. I’ll also say it doesn’t scale well. I’m working with 5  
major models, all of which have very similar functionality (setting  
schedules, selling services) and tried dearly to get everything to work  
in one set of controllers.

At the time it made sense. SchedulesController should handle schedules  
for everything! Well, after about two weeks, I realized it wasn’t  
working. There were too many idiosyncracies within each of the five  
models that the controller was quickly becoming ugly and unwieldly.

I’m a fan of context over consistency. Code in a manner that makes sense  
for your situation. (I might add, your situation _right now_. Don’t get  
too caught up in designing for ages to come.)

- Daniel
