stable-badge

Ubiquo scaffold

The ubiquo_scaffold plugin provides a quick way to generate some of the major code of an Ubiquo modules.

It extend a rails scaffolding functionalities adding typical ubiquo features:

1 Ubiquo scaffolding

1.1 Creating an Ubiquo Resource

Similarly to the Rails scaffold, ubiquo_scaffold creates code to handle resources on an application. It creates a model (with tests), migration, route, ubiquo controller (with tests) and ubiquo views. As an example, let’s create a scaffold for a Book model:

script/generate ubiquo_scaffold book title:string published_at:datetime author_id:integer

REST resources for this model will be created automatically. Check it out:

map.namespace :ubiquo do |ubiquo| ubiquo.resources :books ... end

If we have in our application a ubiquo_i18n plugin, we can generate a ubiquo_scaffold with —translatable param. Learn more about this in the Ubiquo i18n guide.

The ubiquo scaffold will generate the following files in your application, along with some folders and edit one more. Here’s a quick overview of what it creates:

File Purpose
app/views/ubiquo/books/index.html.erb A view to display an index of all books
app/views/ubiquo/books/new.html.erb A view to create a new book
app/views/ubiquo/books/edit.html.erb A view to edit an existing book
app/views/ubiquo/books/show.html.erb A view to display a single book
app/views/ubiquo/books/_form.html.erb A partial to display a form. Used by new and edit views
app/views/ubiquo/books/_submenu.html.erb A partial to display a navigation submenu. It calls books_navlinks partial. Used by all views
app/views/ubiquo/books/_title.html.erb A partial to display a section title. Used by all views
app/views/ubiquo/books/_book.html.erb A partial to display a single book. Used by preview
app/views/navigators/_books_navlinks.html.erb A partial to display a navigation submenu. Called by submenu partial
app/models/book.rb The Book model
test/unit/book_test.rb Unit testing harness for the book model
test/fixtures/books.yml Dummy books for use in testing
config/locales/ca/models/book.yml Catalan book model locales
config/locales/es/models/book.yml Spanish book model locales
db/migrate/20090529095904_create_books.rb Migration to create a books table in your database (your name will include a different timestamp)
app/controllers/ubiquo/books_controller.rb The books controller
test/functional/ubiquo/books_controller_test.rb Functional testing harness for the books controller
app/helpers/ubiquo/books_helper.rb Helper functions to be used from the books ubiquo views

In addition it will also update the following existings files:

File Purpose
config/locales/ca/ubiquo.yml Catalan book ubiquo scaffold locales
config/locales/es/ubiquo.yml Spanish book ubiquo scaffold locales
config/locales/en/ubiquo.yml English book ubiquo scaffold locales
config/locales/ca/models.yml Catalan book model and attributes translations
config/locales/es/models.yml Spanish book model and attributes translations
config/locales/en/models.yml English book model and attributes translations

Keep in mind that due to yaml limitations with UTF-8 output it is useful to have the ya2yaml gem installed.

1.2 Running a Migration

One of the products of the script/generate scaffold command is a database migration.

If you look in the db/migrate/20090529095904_create_books.rb file (remember, your file name will contain a different timestamp), here’s what you’ll find:

class CreateBooks < ActiveRecord::Migration def self.up create_table :books do |t| t.string :title t.datetime :published_at t.integer :author_id t.timestamps end end def self.down drop_table :books end end

At this point, you can use a rake command to run the migration:

$ rake db:migrate

Because you’re working in the development environment by default, this command will apply to the database defined in the development section of your config/database.yml file.

It is possible to run the migration automatically if you pass the -m flag to the ubiquo_scaffold command.

1.3 Configuring menus and navigation tabs

A tab should be automatically added on the main left navigation bar, you can review the file app/views/navigators/_main_navtabs.html.erb to customize it:

<% navigator_left = create_tab_navigator(:tab_options => {}) do |navigator| ... navigator.add_tab do |tab| tab.text = t("application.books") tab.title = t("application.goto", :place => "books") tab.link = ubiquo_books_path tab.highlights_on({:controller => "ubiquo/books"}) tab.highlighted_class = "active" end if permit?("books_management") ... end %> <%= render_tab_navigator(navigator_left) %>

Note that the books_management permission is not automatically created. You can learn the detailed way to manage permissions in the Ubiquo authentication guide.

In app/views/ubiquo/books/_submenu.html.erb is default helper call used to display a navigation ubiquo submenu.

<%= render_navigation_links_section :books %>

At this moment the navigation menu is read from app/views/navigators/_books_navlinks.html.erb. This is generated automatically, check it out:

<% navigator_section = create_link_navigator(:class => 'submenu') do |navigator| ... navigator.add_link do |link| link.text = t("ubiquo.book.index.title") link.url = ubiquo_books_path link.highlights_on({:controller => "ubiquo/books"}) end ... end %> <%= render_link_navigator(navigator_section) %>

Imagine now that you want to add an authors ubiquo resource. If you need it to appear on the same tab that books_, edit the books navigation file app/views/navigators/_booksnavlinks.html.erb and add an authors link:

<% navigator_section = create_link_navigator(:class => 'submenu') do |navigator| ... navigator.add_link do |link| link.text = t("ubiquo.book.index.title") link.url = ubiquo_books_path link.highlights_on({:controller => "ubiquo/books"}) end navigator.add_link do |link| link.text = t("ubiquo.author.index.title") link.url = ubiquo_authors_path link.highlights_on({:controller => "ubiquo/authors"}) end end %> <%= render_link_navigator(navigator_section) %>

You also have to indicate on the main tab navigation app/views/navigators/_main_tabnavs.html.erb to select the Books tab when the item authors is selected:

#app/views/navigators/_main_navtabs.html.erb <% navigator_left = create_tab_navigator(:tab_options => {}) do |navigator| ... navigator.add_tab do |tab| tab.text = t("Books") tab.title = t("application.goto", :place => "books"") tab.link = ubiquo_books_path tab.highlights_on({:controller => "ubiquo/books"}) tab.highlights_on({:controller => "ubiquo/authors"}) tab.highlighted_class = "active" end if permit?("books_management") ... end %> <%= render_tab_navigator(navigator_left) %>

1.4 Views, Helpers, and Controllers Overview

To understand and learn how use and extend all generated files with ubiquo scaffold, we’ll review action by action trying cover all cases.

1.4.1 Index

To start, check out index action in app/controllers/ubiquo/books_controller.rb, we can view that this action only contains a call to filtered_search Book class method. The results are used for paginate method, implemented in ubiquo_core plugin.

The params that paginated_filtered_search method needs are explained with more details in the filters section

class Ubiquo::BooksController < UbiquoController # GET /books # GET /books.xml def index @books_pages, @books = Book.paginated_filtered_search(params) respond_to do |format| format.html # index.html.erb format.xml { render :xml => @books } end end ... end

With new ubiquo version, we have reduced the code generated in index view and moved it to the helper. With this form, if we need do any change, we work with helper usually instead of view.

<h1> <%= render :partial => 'title' %> </h1> <h2> <%= render :partial => 'submenu' %> </h2> <%= render :partial => "shared/ubiquo/feedback" %> <%= show_filter_info %> <%= book_list(@books, @books_pages) %> <% content_for :sidebar do %> <%= show_filters %> <%= help_block_sidebar(t("ubiquo.book.index.help_message")) %> <% end %>

The books_list method renders standard partial located in ubiquo_core plugin. Let’s see its parameters:

Required locals:

  • name – The name of the model listed.
  • headers – An array with columns headers. If the element is a symbol, it’s considerated how a model attribute and list can be sorted by this field. If element is a string, it insn’t sortable.
  • rows – An array with each row of the list. Each row is a hash:
    • id – The id of this element
    • columns – An array with the columns values of this element
    • actions – A result of actions helper method
  • pages – Pagination for this list
  • link_to_new – Link to be used as a button for creating a new model

Optional locals:

  • actions_width – Width (in pixels) of the Actions column (default is 100)
  • hide_actions – Set to true to hide actions (default is false)

The books_actions method returns an array containing all the actions that we want to perform on the instances of the models. By default those actions are edit and delete.

And an example of books ubiquo helper:

module Ubiquo::BooksHelper ... filters helpers ... def book_list(collection, pages, options = {}) render(:partial => "shared/ubiquo/lists/standard", :locals => { :name => 'book', :headers => [:title, :published_at, :author_id], :rows => collection.collect do |book| { :id => book.id, :columns => [ book.title, book.published_at, book.author_id, ], :actions => book_actions(book) } end, :pages => pages, :link_to_new => link_to(t("ubiquo.book.index.new"), new_ubiquo_book_path, :class => 'new') }) end private def book_actions(book, options = {}) actions = [] actions << link_to(t("ubiquo.edit"), [:edit, :ubiquo, book]) actions << link_to(t("ubiquo.remove"), [:ubiquo, book], :confirm => t("ubiquo.book.index.confirm_removal"), :method => :delete ) actions end end

You can also use related fields as columns (ubiquo_categories should work too), an example:

def article_list(collection, pages, options = {}) render(:partial => "shared/ubiquo/lists/standard", :locals => { :name => 'article', :headers => [:title, :description, :"author.name", :"section.name", :publish_date], :rows => collection.collect do |article| { :id => article.id, :columns => [ article.title, article.description, article.author.try(:name), article.section.try(:name), article.publish_date, ], :actions => article_actions(article) } end, :pages => pages, :link_to_new => link_to(t("ubiquo.article.index.new"), new_ubiquo_article_path, :class => 'new') }) end

2 Adding extra data to scaffold initialization

By now, we have seen how to create a scaffold for a given model. It creates physical files and some code to get it working. This section is focused on expanding the previous behaviour and introducing new features.

2.1 Adding media

Now it is possible to add media from scaffold. Media resources will appear in model, as a media_attachment directive, and in form, with a media selector attached to a new form box.

script/generate ubiquo_scaffold Book title:string published_at:datetime author_id:integer --media media_field_1,media_field_2

The previous directive will generate two media relations through media_field_1 and media_field_2 names.

2.2 Adding categories

Similarly as adding media, we can categorize our model from scaffold. It will generate a categorization in model and a category selector in form.

script/generate ubiquo_scaffold book title:string published_at:datetime author_id:integer --categorized category_set_1,category_set_2

This directive will generate two category relations from our model to category_set_1 and category_set_2.

2.3 Adding model relations

Finally, and in the same way as the previous sections, we will be able to generate relations with other models. All relations created by scaffold will benefit of relation selector helper on forms and will generate a properly relation on model (has_many or belongs_to, depending on the params supplied).

script/generate ubiquo_scaffold book title:string published_at:datetime author_id:integer --belongs_to author --has_many pages

The previous directive will generate a has_many relation to Page model and a belongs_to relation to Author through author_id field. Both relations will be seen in form as relation selector helpers.

This guide is not finished yet.

3 Changelog

Lighthouse tickets