{"id":817,"date":"2010-03-10T16:03:05","date_gmt":"2010-03-10T19:03:05","guid":{"rendered":"http:\/\/blog.plataformatec.com.br\/?p=817"},"modified":"2010-04-22T14:55:40","modified_gmt":"2010-04-22T17:55:40","slug":"show-your-objects-baby","status":"publish","type":"post","link":"https:\/\/blog.plataformatec.com.br\/2010\/03\/show-your-objects-baby\/","title":{"rendered":"Show your objects baby!"},"content":{"rendered":"
We have been having some projects lately that needed a lot of admin CRUDs and pages showing a list of attributes, and we were getting bored of copy and paste code like this in our show pages, for every single attribute:<\/p>\n
\r\n\r\n Name<\/strong>
\r\n <%= @person.name %>\r\n<\/p>\r\n<\/pre>\nWe had already created some helper to do the work for us, but having this helper being copied from one project to another wasn’t that DRY. That’s when we decided to create ShowFor<\/a>.<\/p>\nShowFor<\/a> is a DSL to help you showing a list of attributes, with I18n, perfect for show pages in CRUD interfaces. It allows you to replace code\/html duplication in your views using a nice syntax. Let’s see what we can do.<\/p>\nAttributes<\/h3>\n
Let’s imagine we have a Person model, which has first_name, last_name, age, photo, and confirmed attributes. The following lines show a list of values for a specific person:<\/p>\n
\r\n<% show_for @person do |p| %>\r\n <%= p.attribute :first_name %>\r\n <%= p.attribute :last_name %>\r\n <%= p.attribute :confirmed? %>\r\n <%= p.attribute :created_at, :format => :short %>\r\n <%= p.attribute :age, :if_blank => \"No age\" %>\r\n\r\n <% p.attribute :photo do %>\r\n <%= image_tag(@person.photo_url) %>\r\n <% end %>\r\n<% end %>\r\n<\/pre>\nHere is an example output you will get:<\/p>\n
\r\n\r\n First name<\/strong>
Carlos<\/p>\r\n Last name<\/strong>
Antonio<\/p>\r\n Confirmed?<\/strong>
Yes<\/p>\r\n Created at<\/strong>
08 Mar 11:30<\/p>\r\n Age<\/strong>
24<\/p>\r\n Photo<\/strong>
\r\n \r\n <\/p>\r\n<\/div>\r\n<\/pre>\nAs you can see, you are going to get a default html markup, with classes and ids to help you design with CSS. And if you noticed, we are using extra options in some attributes, lets take a look at some of them:<\/p>\n
\n:format<\/code> lets you pass any format that will be used together with i18n, for date\/time attributes only, as you would use with the l<\/code> helper.<\/li>\n:if_blank<\/code> specifies what to show if the attribute is blank. It may have a default value from i18n.<\/li>\ndo...end<\/code>: using blocks you can handle the content for that specific attribute by yourself, as we have done in this example for the photo<\/code> attribute.<\/li>\n<\/ul>\nBoolean attributes, as our :confirmed<\/code>, also have a default for true<\/code> and false<\/code> values, and can be configured through i18n. If you want to say “Yup” and “Nope” instead of “Yes” and “No” respectively, just change your i18n file. You can also pass a :escape<\/code> option to not escape the value (true<\/code> by default).<\/p>\nAssociations<\/h3>\n
ShowFor<\/a> also works with associations. For instance, we can easily add that a Person belongs to a City with a name attribute and that it has and belongs to many Tags. To handle the former, we can do:<\/p>\n\r\n<%= p.association :city %>\r\n<\/pre>\nShowFor<\/a> will guess the right attribute to show by looking into all possibilities configured in ShowFor.association_methods<\/code> and in this case choosing :name. But of course, you can change it as you need, on-the-fly:<\/p>\n\r\n<%= p.association :city, :using => :full_name %>\r\n<%= p.attribute :full_name, :in => :city %>\r\n<\/pre>\nBoth calls above will have the same output, just choose the one which suits you better. <\/p>\n
Handling collections is easy as belongs_to associations. You can just pass the association to ShowFor<\/a> and it will know whether it’s a collection or not, generating a list of elements using ul<\/code> and li<\/code> tags.<\/p>\n\r\n<%= p.association :tags %>\r\n<\/pre>\nHowever, if you want to render the collection inline, you can use :to_sentence or :join as options:<\/p>\n
\r\n<%= p.association :tags, :to_sentence => true %>\r\n<%= p.association :tags, :join => ',' %>\r\n<\/pre>\nIt’s also possible to pass a block to the collection. ShowFor<\/a> will create the wrapper tag (ul<\/code> by default in this case) and will yield<\/code> each element in the collection for you to handle it:<\/p>\n\r\n<% a.association :tags do |tag| %>\r\n
- <%= link_to tag.name, tag %><\/li>\r\n<% end %>\r\n<\/pre>\n
Labels<\/h3>\n
You may have noticed ShowFor<\/a> has a default label using the strong<\/code> html tag. It also exposes you this as a helper, so you can use it whenever you wish:<\/p>\n\r\n <%= p.label :first_name %>\r\n <%= p.label :age, :id => 'person_age' %>\r\n\r\n First name<\/strong>\r\n Age<\/strong>\r\n<\/pre>\nInstallation<\/h3>\n
ShowFor<\/a> is already compatible with Rails 3, at the time of this writing in version 0.2.0. You can just follow the instructions in the README<\/a> to get it installed.<\/p>\nIf you are using Rails 2.3.x, take a look at the 0.1 branch<\/a>, and follow the installations in the README<\/a> for this branch to get it up and running.<\/p>\nPlease don’t forget to run the generator and take a look at the initializer, it will allows you configure several parts of ShowFor<\/a>.<\/p>\n\r\nscript\/generate show_for_install\r\n<\/pre>\nClosing<\/h3>\n
ShowFor<\/a> helps you to show your objects easily with a default html markup, and can be totally configured to suit your needs. It has been helping us in every project, and we hope it may help you too. If you have any doubt, please take a look at the README<\/a>, there are a lot of examples and documentation there.<\/p>\nAnd what about you? Do you have any helper you use every single day that might be transformed in a plugin\/gem? Do not hesitate on doing this, we would be glad to see your work.<\/p>\n
Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"
We have been having some projects lately that needed a lot of admin CRUDs and pages showing a list of attributes, and we were getting bored of copy and paste code like this in our show pages, for every single attribute: Name We had already created some helper to do the work for us, but … \u00bb<\/a><\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[1],"tags":[23,7,79],"aioseo_notices":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/817"}],"collection":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/comments?post=817"}],"version-history":[{"count":16,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/817\/revisions"}],"predecessor-version":[{"id":907,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/817\/revisions\/907"}],"wp:attachment":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/media?parent=817"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/categories?post=817"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/tags?post=817"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}