Creating a Basic Question-List Interface

The presentaiton was a hit. The next step is to make the “take the experiment” feature less fakey, by incorporating pretests and posttests. My inspiration for how to do this comes from MediaLab, which I worked with previously.

Every Question will belong to a QuestionList. Every QuestionList can belong to any number of conditions. There will also be a model that ties QuestionLists into Conditions and one that ties QuestionOptions into Questions. The table schemes are something like :


Question
-ID
-Name
-Display
-Type
-ListID

-QuestionList
-ID
-Name
-Description

QuestionOptions
-ID
-QuestionID
-Name
-OptionText

QuestionListConditions
-ID
-ConditionID
-QuestionListID

ruby script/generate model question
ruby script/generate model question_list
ruby script/generate model question_option
ruby script/generate model question_list_condition

Then generate the appropriate models

Now to through the migrations, added fields as necessary

015_create_questions.rb

class CreateQuestions < ActiveRecord::Migration
def self.up
create_table :questions do |t|
t.column :name, :string
t.column :display, :text
t.column :type, :integer
t.column :list_id, :integer
end
end

def self.down
drop_table :questions
end
end

016_create_question_lists.rb

class CreateQuestionLists < ActiveRecord::Migration
def self.up
create_table :question_lists do |t|
t.column :name, :string
t.column :description, :text
end
end

def self.down
drop_table :question_lists
end
end

017_create_question_options.rb

class CreateQuestionOptions < ActiveRecord::Migration
def self.up
create_table :question_options do |t|
t.column :question_id, :integer
t.column :name, :string
t.column :optiontext, :text
end
end

def self.down
drop_table :question_options
end
end

018_create_question_list_conditions.rb

class CreateQuestionListConditions < ActiveRecord::Migration
def self.up
create_table :question_list_conditions do |t|
t.column :condition_id, :integer
t.column :question_list_id, :integer
end
end

def self.down
drop_table :question_list_conditions
end
end

Then rake db:migrate

Next, we’ll create the controller and the scaffold for questions and question_lists, as was done on day one.

ruby script/generate controller manage_questions
ruby script/generate controller manage_question_lists

Then generate the static scaffolds, like in day two.

ruby script/generate scaffold question manage_questions
ruby script/generate scaffold question_list manage_question_lists

Now create controllers for question_options and question_list_conditions. We are actually creating two classes of controllers here — the basic steps of setting up an experiment and the more mundane database-interface controllers. But more on that in a bit. For now:

ruby script/generate controller manage_question_options
ruby script/generate controller manage_question_list_conditions
ruby script/generate scaffold question_option manage_question_options
ruby script/generate scaffold question_list_condition manage_question_list_conditions

Now add the interface code as done two days ago to our four new controllers:

layout “notesonrails”

And modify /views/layouts/notesonrails.html as appriate. The goal is to provide access to every controller while differentiating controllers designed for use, for debugging, for output, and for the experiment itself:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title><%= controller.controller_name %>: <%= controller.action_name %></title>
<%= stylesheet_link_tag ‘scaffold’ %>
</head>
<body>

<p style="color: green"><%= flash[:notice] %></p>
<h1>Notes on Rails Admin Interface</h1>
<div id="menu_area">
<p>Create an Experiment:
<%= link_to ( "Experiments",
:controller => :manage_experiments, :action => :index ) %>,
<%= link_to ( "Conditions",
:controller => :manage_conditions,
:action => :index ) %>,
<%= link_to ( "Question Lists",
:controller => :manage_question_lists ) %>,
<%= link_to ( "Questions",
:controller => :manage_questions ) %>,
<%= link_to ( "Fields",
:controller => :manage_notes_fields ) %>,
<%= link_to ( "Records",
:controller => :manage_notes_records ) %>,
</p>

<p>Other Features:
<%= link_to ( "Notes",
:controller => :manage_notes ) %>,
<%= link_to ( "Students",
:controller => :manage_students ) %>,
<%= link_to ( "QuestionList Conditions",
:controller => :manage_question_list_conditions ) %>,
<%= link_to ( "Question Options",
:controller => :manage_question_options ) %> |
<%= link_to ( "Output",
:controller => :output ) %> |
<b><%= link_to ( "Take an Experiment!",
:controller => :students ) %></b></p>
</div>
<%= yield %>

</body>
</html>

Next up, alter the manage_question_lists controller so that one may pick several conditions for the question list to b belong too

in new(), add the line “@experiments = Experiment.find(:all)” and in _form.rhtml

Now let’s add some check boxes to the manage_question_lists controller so that we can associate it with our conditions

Firs,t let’s add some methods on question_list_condition.rb controller:

class QuestionListCondition < ActiveRecord::Base
def self.destroy_by_condition_id_question_list_id(condition_id,question_list_id)
to_destroy = find_by_condition_id_question_list_id(condition_id,question_list_id)

to_destroy.destroy if to_destroy
end

def self.add_by_condition_id_question_list_id(condition_id,question_list_id)
to_add = find_by_condition_id_question_list_id(condition_id,question_list_id)

if to_add
return to_add
else
to_add = QuestionListCondition.new(
:condition_id => condition_id,
:question_list_id => question_list_id
)
to_add.save
return to_add
end
end

def self.find_by_condition_id_question_list_id(condition_id,question_list_id)

to_return = find(
:first,
:conditions => {
:condition_id => condition_id,
:question_list_id => question_list_id
}
)

to_return
end
end

update four functions in manage_question_lists_controller.rb:

def new
@question_list = QuestionList.new
@experiments = Experiment.find(:all)
end

def create
@question_list = QuestionList.new(params[:question_list])
@result_of_save = @question_list.save

@question_list_conditions = params[:selected_condition]
for question_list_condition in @question_list_conditions
@question_list_condition_id = question_list_condition[0].to_i
@question_list_condition_show = question_list_condition[1].to_i
if @question_list_condition_show == 1
QuestionListCondition.add_by_condition_id_question_list_id(@question_list_condition_id,@question_list.id)
else
QuestionListCondition.destroy_by_condition_id_question_list_id(@question_list_condition_id,@question_list.id)
end
end

if @result_of_save
flash[:notice] = ‘QuestionList was successfully created.’
redirect_to :action => ‘list’
else
render :action => ‘new’
end

end

def edit
@question_list = QuestionList.find(params[:id])
@experiments = Experiment.find(:all)

end

def update
@question_list = QuestionList.find(params[:id])

@question_list_conditions = params[:selected_condition]
for question_list_condition in @question_list_conditions
@question_list_condition_id = question_list_condition[0].to_i
@question_list_condition_show = question_list_condition[1].to_i
if @question_list_condition_show == 1
QuestionListCondition.add_by_condition_id_question_list_id(@question_list_condition_id,@question_list.id)
else
QuestionListCondition.destroy_by_condition_id_question_list_id(@question_list_condition_id,@question_list.id)
end
end

if @question_list.update_attributes(params[:question_list])
flash[:notice] = ‘QuestionList was successfully updated.’
redirect_to :action => ‘show’, :id => @question_list
else
render :action => ‘edit’
end
end</i>

and then the _form.rhtml partial:

<i><%= error_messages_for ‘question_list’ %>

<!–[form:question_list]–>
<p><label for="question_list_name">Name</label><br/>
<%= text_field ‘question_list’, ‘name’ %></p>

<p><label for="question_list_description">Description</label><br/>
<%= text_area ‘question_list’, ‘description’, :rows=>4 %></p>

<p><label for="question_list_conditions">Conditions</label><br />
<% for experiment in @experiments %>
<p><%= experiment.name %>
<% @conditions = Condition.find_conditions_array(experiment.id) %>
<% for condition in @conditions %>
<br /><%= check_box :selected_condition, condition.id %>
<%= condition.name %>
<% end %></p>
<% end %>

<!–[eoform:question_list]–>

Excellent. To finish up today, just edit the administrative question_list_condition view, as right now it’s blank because it’s looking for content_columns, of which it has none:

—-

We won’t do everything for this scaffolding, but we will fix this list and make some code more portable.

In experiment.rb, change find_name_by_id to

def self.find_name_by_id(selected_id)
found_object = find(selected_id)
@to_return = found_object.name
end

now, copy and paste the same code into question_list.rb, while also adding

validates_presence_of :name, :description

to the top

Last, change list.rhtml to:

<h1>Listing question_list_conditions</h1>

<table>
<tr>
<th>ID</th>
<th>Condition</th>
<th>Question List</th>
</tr>
<% for question_list_condition in @question_list_conditions %>
<tr>
<td><%= question_list_condition.id %></td>
<td><%= Condition.find_name_by_id(question_list_condition.condition_id) %></td>
<td><%= QuestionList.find_name_by_id(question_list_condition.question_list_id) %></td>
</tr>
<% end %>
</table>

<%= link_to ‘Previous page’, { :page => @question_list_condition_pages.current.previous } if @question_list_condition_pages.current.previous %>
<%= link_to ‘Next page’, { :page => @question_list_condition_pages.current.next } if @question_list_condition_pages.current.next %>

<br />

<%= link_to ‘New question_list_condition’, :action => ‘new’ %>

Tomorrow: adding questions!

Leave a Reply

Your email address will not be published. Required fields are marked *