Backend Interface - Create a Poll |
Outputting to a partial ![]() |
Module Tutorial: User Polling / Rating: Backend Interface - Poll List
The administration interfaces of CMS’s tend to need display a lot of data, and so tables are a large part of the glue that binds them together. Webiva is no different, and uses a class called ActiveTable to handle most of the tables in the admin interface. Using ActiveTable makes it easy to make paginated, sortable and searchable tables that update via Ajax calls. While creating an ActiveTable is a little more involved than just writing a few <table> and <td> tags, it’s generally the same five steps. The controller needs to be able to interact with the view, and vice versa, in a streamlined manner. The steps are:
- Make a class level
active_tablecall to name the table, the affected model and the different columns of the table - Create a
display_[table_name]method that will generate the table output and display a partial if necessary - Call
display_[table_name]from your index controller method to generate the table the first time - Call
render_active_table(table_name)in your index view to output the table and containing div - Display a partial called
_table_name.html.erbthat callsactive_table_forand actually creates the table
This may seem like a lot of work, but the actual amount of code required is pretty minimal. Let’s go through each step and get a table up and running to display our polls.
Step 1: Defining the table
Let’s define the active table that we’re going to generate by adding in a table definition to the controller. Right above the dummy index method in PollDemo::ManageController, add the following couple lines of code:
vendor/modules/poll_demo/app/controllers/poll_demo/manage_controller.rb
active_table :poll_table, PollDemoPoll,
[:check,:question, :name,
hdr(:number,:response_count,:label => 'Response'),"Results",:created_at]
This defines an ActiveTable called :poll_table based on the PollDemoPoll model. It also tells the system that there are 5 columns. You can define columns for an active_table by using the hdr(:header_type,:field_name,:options => {}) syntax. See the API docs for more information on the available header types. There are also shortcuts you can use. Using the symbol :check will add a blank-header column just the right size for a checkbox. Using a different symbol name, like :question or :name will create a string header column on a model database field of that name. Adding a string, like “Results”, will create a static header that cannot be sorted or searched.
Steps 2&3: Creating and calling the display method
Moving on to step two, we need to create a method called display_[table_name], or in our case, display_poll_table. Add the following two methods into the controller, replacing the current index method:
vendor/modules/poll_demo/app/controllers/poll_demo/manage_controller.rb
def display_poll_table(display=true)
@tbl = poll_table_generate(params,:order => 'created_at DESC')
render :partial => 'poll_table' if display
end
def index
cms_page_path ["Content"], "Poll Demo"
display_poll_table(false)
end
You’ll notice the first method, display_poll_table, takes an argument which defaults to true. This allows us to use the method both as a controller method and as a helper method (from index), but only render the partial in the form case. The poll_table_generate method is a method that is created for us automatically by the active_table call we added in Step 1. It takes the parameters hash (params) and any additional options we want to add (such as a default order argument) and returns an ActiveTable object we will need in the view.
All we’ve done to the index method is add a call to display_poll_table, overriding the default parameter to false, so that the table partial doesn’t get rendered and we still render the default index.html.erb template.
Step 4: Modifying the index view to render the table
Now we need to actually get our table rendered in the view. To that end, let’s open up index.html.erb and add in the line that will get that done for us. We need to add a call to <%= active_table_render(:poll_table) %>. The whole modified file is shown below:
vendor/modules/poll_demo/app/views/poll_demo/manage/index.html.erb:
<% action_panel do |p| -%>
<%= p.link "Create a new Poll", :action => 'edit', :icon => 'add.gif' -%>
<% end -%>
<hr/>
<div class='admin_content'>
<%= active_table_render :poll_table -%>
</div>
This call doesn’t actually do very much; all it’s going to do is wrap our partial in a <div id='poll_table'> and render the partial _poll_table.html.erb.
Step 5: Rendering the table
Now for the actual meat of the call: rendering the table itself. ActiveTable, for the most part, stays out of the way when we are actually rendering our row content. Create a new file called _poll_table.html.erb and add in the following code:
vendor/modules/poll_demo/app/views/poll_demo/manage/_poll_table.html.erb:
<% active_table_for :poll_table, @tbl do |t| -%>
<% active_tr 'poll',t.id do |tr| -%>
<td><%= tr.checkbox -%></td>
<td><%= link_to h(t.name), :action => 'edit',:path => [ t.id ] -%></td>
<td><%= h(t.question) -%></td>
<td><%= t.response_count -%></td>
<td><%= t.results.values.join(" / ") if t.results -%></td>
<td><%= t.created_at.to_s(:short) -%></td>
<% end -%>
<% end -%>
There are a couple things to note about this view. First, the call to active_table_for is doing most of the work creating the table and the headers. It is responsible for generating the table, the sortable and searchable headers and automatically updating the table via AJAX calls to display_poll_table. It is configurable with a number of different options to change the refresh URL, the div to update, etc., but if you follow the naming convention described above you can get away with just calling it with the name of the table (:poll_table) and the table data we generated in display_poll_table (@tbl). It will then call the block once for each row of the table, passing a PollDemoPoll object in so we can fill in the table cells.
The active_tr helper method is useful for generating rows that highlight and check a per-entry checkbox when clicked, but if we don’t need those, we could also have used a simple <tr> tag. The rest of the view is just a bunch of <td> tags wrapping standard rails view code. Try adding a couple of polls and playing around with the table. You can search and reorder on the string fields and the date fields.
Adding some actions
We’ve now got a working table; however, we seem to have a bunch of checkboxes that don’t actually do anything. Not to worry, we’ll be adding some actions next. Let’s tell the table about a couple of actions we want to be able to perform on our polls. Delete the active_table line (top line) of the _poll_table.html.erb file and add the following three lines to read:
vendor/modules/poll_demo/app/views/poll_demo/manage/_poll_table.html.erb:
<% active_table_for :poll_table, @tbl,
:actions => [['Reset','reset',"Wipe these polls' responses?"],
['Delete','delete','Delete the selected polls?']] do |t| -%>
Reload the index page and you should see a couple of buttons below the table along with ‘check all / uncheck all’ links. You can check a couple of polls and click ‘Delete’ and the system should ask you if you are sure. Go ahead and click ‘Ok’ - the table will reload, but it won’t actually do anything because we haven’t written the action code yet. Open up the PollDemo::ManageController and add the following code at the top of the display_poll_table method (before the poll_table_generate call):
vendor/modules/poll_demo/app/controllers/poll_demo/manage_controller.rb
def display_poll_table(display=true)
active_table_action('poll') do |act,pid|
case act
when 'delete': PollDemoPoll.destroy(pid)
when 'reset': PollDemoPoll.find(pid).map(&:reset!)
end
@tbl = poll_table_generate(params,:order => 'created_at DESC')
render :partial => 'poll_table' if display
end
We also need to add a reset! method to the PollDemoPoll class to clear its responses. Add the following somewhere in the class definition:
vendor/modules/poll_demo/app/models/poll_demo_poll.rb
def reset!
self.update_attributes(:response_count => 0,:results => nil)
end
We should now be able to create, edit, search, sort, delete and reset polls. Not bad for ~50 Lines of controller code and ~20 lines of view code. The next step is to actually output something on the front end of the website for an end user.
Backend Interface - Create a Poll |
Outputting to a partial ![]() |

Backend Interface - Create a Poll