This post was updated on 04-27-08 to reflect the improved design. I'm using the RubyOnRails methods as this is where Stage was born, but Stage is available for Merb as well.
I've just completed a new generator called stage. This is a direct copy/modification of the scaffold generator included with Rails 2.0.2.
Stage was born out of a desire to remove as much code as possible from the view. I didn't want to create a new markup, I wanted to use the existing architecture more efficiently.
To use Stage, you first need to grab it:
sudo gem install stage
Then you use stage just like scaffold:
./script/generate stage author first_name:string last_name:string
exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/authors
exists app/views/layouts/
create app/views/data/
create app/views/authors/index.html.erb
create app/views/authors/show.html.erb
create app/views/authors/new.html.erb
create app/views/authors/edit.html.erb
create app/views/authors/_form.html.erb
create app/views/authors/_data.html.erb
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/author.rb
create test/unit/author_test.rb
create test/fixtures/authors.yml
create db/migrate
create db/migrate/001_create_authors.rb
create app/controllers/authors_controller.rb
create app/helpers/authors_helper.rb
route map.resources :authors
So, what's different? With the exception of the index view, the contents have changed quite a bit.
Edit:
<h1>Editing Author</h1>
<%= render :partial => "form" %>
<%= link_to 'Show', @author %> |
<%= link_to 'Back', authors_path %>
New:
<h1>New Author</h1>
<%= render :partial => "form" %>
<%= link_to 'Back', authors_path %>
Show:
<%= render :partial => "data" %>
<%= link_to 'Edit', edit_author_path(@author) %> |
<%= link_to 'Back', authors_path %>
And theres a new partial called form. As you can see this is called by edit and new:
<%
submit_label = "Update"
submit_label = "Create" if @author.new_record?
-%>
<%= error_messages_for :author %>
<% form_for(@author) do |f| %>
<%= render :partial => "data" %>
<p> <%= f.submit submit_label %> </p>
<% end %>
We've now removed the duplication in new, edit and show by having them all reference the data partial.
I've had this construct for a while, but the data partial always ended up with too much code. If I'm in edit mode, show the input tag, else show the text, etc..., etc...
It could get rather ugly. So, I decided to really start using the helpers. I have used them before when there would have been "too much" code in the view. I guess I've changed my definition of "too much".
Here's the data partial:
<p>
<b>First name</b><br/>
<%= author_first_name_value %>
</p>
<p>
<b>Last name</b><br/>
<%= author_last_name_value %>
</p>
As you can see I am calling a <model>_<attribute>_value method which will give me back the correct form or show value. This construct is used to avoid naming collisions. I had initially designed it without namespacing the methods with the model name, but quickly discovered that was a bad idea.
The @action_name instance variable determines how I'm to render the information. Luckily both Merb and Rails have this same variable.
These methods are defined in the Helper:
module AuthorsHelper
def author_first_name_value
if @action_name == "show"
h @author.first_name
else
text_field_tag "author[first_name]", @author.first_name
end
end
def author_last_name_value
if @action_name == "show"
h @author.last_name
else
text_field_tag "author[last_name]", @author.last_name
end
end
end
I opted on creating a method for each attribute and a clearly outlined "if" block to make modifications easier.
I hope you find this useful and it fits your idea of view structure.
Btw, thanks to Greg Houston for his source formatting tool. It made this post look a lot better than it would have without it.
