- Rhomobile Beginner's Guide
- Abhishek Nalwaya
- 2519字
- 2025-03-31 04:29:54
Linking views to the homepage
Now we will add a link to the default homepage of our Rhodes application that redirects us to the index action of the employee controller.
Time for action – Linking the employee view to the homepage
We will first link employee views on an iPhone. This index page in an app directory is the default homepage, which will be loaded in our application.
You can edit the generated ERB files to customize the HTML as desired. Typically, you will provide links to the employee index page from the home screen. Below is the generated top level index.erb
file for our application:
<div class="pageTitle"> <h1>EmployeeApplication</h1> </div> <div class="toolbar"> <% if SyncEngine::logged_in > 0 %> <div class="leftItem blueButton"> <a href="<%= url_for :controller => :Settings, :action => :do_sync %>">Sync</a> </div> <div class="rightItem regularButton"> <a href="<%= url_for :controller => :Settings, :action => :logout %>">Logout</a> </div> <% else %> <div class="rightItem regularButton"> <a href="<%= url_for :controller => :Settings, :action => :login %>">Login</a> </div> <% end %> </div> <div class="content"> <ul> <li> <a href="#"><span class="title"> Add Links Here...</span><span class="disclosure_indicator"/></a> </li> </ul> </div>
To provide a link to the Employee index page and templates, you can replace the list item with the title Add links here with:
<a href="<%= url_for :controller => :Employee %>">Employee</a>
Let's stop for a moment to consider how we generated this link. url_for
is a helper method of Rhodes that generates a link. We have to pass the controller name and action name as a parameter to create the desired link. We will discuss this in detail as we proceed.
If you look at url_for
carefully, there are no parentheses and if you come from the school of Java style of coding, you might be surprised that Ruby doesn't insist on parentheses around method parameters. However, you can always add them if you like.
Now, we will build our code using rake run:iphone
and as you navigate you can see the following screens :
- Default Index page in app folder: This is the homepage of our application that will be loaded once the application is started:
- Listing all employees: The easiest place to start looking at functionality is with the code that lists all the employees. Open the file
app/employee/employee_controller.rb
and look at the index action:def index @employees = Employee.find(:all) render end
This code sets the @employees
instance variable to an array of all employees in the database. Employee.find(:all)
calls the Employee model to return all of the employees that are currently in the database, with no limiting conditions. Rhodes makes all of the instance variables from the action available to the view. Here's app/employee/index.erb
:
<div class="pageTitle"> <h1>Employees</h1> </div> <div class="toolbar"> <div class="leftItem regularButton"> <a href="<%= Rho::RhoConfig.start_path %>">Home</a> </div> <div class="rightItem regularButton"> <a class="button" href="<%= url_for :action => :new %>">New</a> </div> </div> <div class="content"> <ul> <% @employees.each do |employee| %> <li> <a href="<%= url_for :action => :show, :id => employee.object %>"> <span class="title"><%= employee.name %></span><span class="disclosure_indicator"></span> </a> </li> <% end %> </ul> </div>
This view iterates over the contents of the @employees
array to display content and links. A few things to note in the view:
- The page is divided into three part with page title, toolbar, and content
Rho::RhoConfig.start_path
redirects to the default page mentioned inrhoconfig.txt
url_for
helper is an inbuilt method to create a link- Creating a new employee: Creating a new employee involves two actions. The first is the new action, which instantiates an empty employee object:
def new @employee = Employee.new render :action => :new end The new.html.erb view displays this empty employee to the user: <div class="pageTitle"> <h1>New <%= @employee.title %></h1> </div> <div class="toolbar"> <div class="leftItem backButton"> <a class="cancel" href="<%= url_for :action => :index %>">Cancel</a> </div> </div> <div class="content"> <form method="POST" action="<%= url_for :action => :create %>"> <input type="hidden" name="id" value="<%= @employee.object %>"/> <ul> <li> <label for="employee[name]" class="fieldLabel">Name</label> <input type="text" name="employee[name]" <%= placeholder("Name") %> /> </li> <li> <label for="employee[company]" class="fieldLabel">Company</label> <input type="text" name="employee[company]" <%= placeholder("Comapany") %> /> </li> <li> <label for="employee[address]" class="fieldLabel">Address</label> <input type="text" name="employee[address]" <%= placeholder("Address") %> /> </li> <li> <label for="employee[age]" class="fieldLabel">Age</label> <input type="text" name="employee[age]" <%= placeholder("Age") %> /> </li> <li> <label for="employee[gender]" class="fieldLabel">Gender</label> <input type="text" name="employee[gender]" <%= placeholder("Gender") %> /> </li> <li> <label for="employee[salary]" class="fieldLabel">Salary</label> <input type="text" name="employee[salary]" <%= placeholder("Salary") %> /> </li> </ul> <input type="submit" class="standardButton" value="Create"/> </form> </div>
We have just created an HTML form. When the user clicks the Create button on this form, the application will send information back to the create method of the controller.
def create @employee = Employee.create(@params['employee']) redirect :action => :index end
The create action instantiates a new employee object from the data supplied by the user on the form, which Rhodes makes available in the
params
hash. After saving this hash the controller will redirect to index action. - Showing an Individual employee: When we click any employee name on the index page, Rhodes interprets this as a call to the show action for the resource, and passes
:id
as parameter. Here's the show action:def show @employee = Employee.find(@params['id']) if @employee render :action => :show else redirect :action => :index end end
The show action uses
Employee.find
to search for a single record in the database by its ID value. After finding the record, Rhodes displays it by usingshow.erb
:<div class="pageTitle"> <h1><%= @employee.name %></h1> </div> <div class="toolbar"> <div class="leftItem backButton"> <a href="<%= url_for :action => :index %>">Back</a> </div> <div class="rightItem regularButton"> <a href="<%= url_for :action => :edit, :id => @employee.object %>">Edit</a> </div> </div> <div class="content"> <ul> <li> <div class="itemLabel">Name</div> <div class="itemValue"><%= @employee.name %></div> </li> <li> <div class="itemLabel">Company</div> <div class="itemValue"><%= @employee.company %></div> </li> <li> <div class="itemLabel">Address</div> <div class="itemValue"><%= @employee.address %></div> </li> <li> <div class="itemLabel">Age</div> <div class="itemValue"><%= @employee.age %></div> </li> <li> <div class="itemLabel">Gender</div> <div class="itemValue"><%= @employee.gender %></div> </li> <li> <div class="itemLabel">Salary</div> <div class="itemValue"><%= @employee.salary %></div> </li> </ul> </div>
- Editing the page to modify the employee details: Like creating a new employee, editing an employee is a two-part process. The first step is a request to a particular employee. This calls the edit action in the controller:
def edit @employee = Employee.find(@params['id']) if @employee render :action => :edit else redirect :action => :index end end
After calling the edit action it will render the
edit.erb
file:<div class="pageTitle"> <h1>Edit <%= @employee.name %></h1> </div> <div class="toolbar"> <div class="leftItem backButton"> <a href="<%= url_for :action => :show, :id => @employee.object %>">Cancel</a> </div> <div class="rightItem regularButton"> <a class="button" href="<%= url_for :action => :delete, :id => @employee.object %>">Delete</a> </div> </div> <div class="content"> <form method="POST" action="<%= url_for :action => :update %>"> <input type="hidden" name="id" value="<%= @employee.object %>"/> <ul> <li> <label for="employee[name]" class="fieldLabel">Name</label> <input type="text" name="employee[name]" value="<%= @employee.name %>" <%= placeholder( "Name" ) %> /> </li> <li> <label for="employee[company]" class="fieldLabel">Company</label> <input type="text" name="employee[company]" value="<%= @employee.company %>" <%= placeholder( "Company" ) %> /> </li> <li> <label for="employee[address]" class="fieldLabel">Address</label> <input type="text" name="employee[address]" value="<%= @employee.address %>" <%= placeholder( "Address" ) %> /> </li> <li> <label for="employee[age]" class="fieldLabel">Age</label> <input type="text" name="employee[age]" value="<%= @employee.age %>" <%= placeholder( "Age" ) %> /> </li> <li> <label for="employee[gender]" class="fieldLabel">Gender</label> <input type="text" name="employee[gender]" value="<%= @employee.gender %>" <%= placeholder( "Gender" ) %> /> </li> <li> <label for="employee[salary]" class="fieldLabel">Salary</label> <input type="text" name="employee[salary]" value="<%= @employee.salary %>" <%= placeholder( "Salary" ) %> /> </li> </ul> <input type="submit" class="standardButton" value="Update"/> </form> </div>
This is a normal HTML form. Submitting the form created by this view will invoke the update action within the controller:
def update @employee = Employee.find(@params['id']) @employee.update_attributes(@params['employee']) if @employee redirect :action => :index end
In the update action, Rhodes first uses the
:id
parameter passed back from the edit view to locate the database record that's being edited. Theupdate_attributes
call then takes the rest of the parameters from the request and applies them to this record. - Deleting an employee: Finally, clicking on Delete links sends the associated ID to the delete action:
def delete @employee = Employee.find(@params['id']) @employee.destroy if @employee redirect :action => :index end
Rhode's philosophy is to make a developer's life easy, as you have learned with a single command an elementary CRUD application is ready in minutes. Similarly, we can build and test the same code for other smart phones. However, a few minor changes will be required for BlackBerry in .bb.erb
files. This is because lower versions of Blackberry support very less CSS and JavaScript. So, to overcome this limitation we have separate views for Blackberry.
Until now we have seen and tested our application on iPhone. For other smart phones, you can run it in the same way. But for Blackberry we have to edit .bb.erb
files.
For Blackberry, add this line to index.bb.erb
:
<%= link_to "Employee", :controller => :Employee%>
link_to
is a helper provided by Rhodes to create a link similar to url_for
.

Now you can navigate the employee model on Blackberry in a similar way as we did on iPhone.
Have a go hero – Exploring url_for
We will explore the inbuilt helper of Rhodes to create a link with the following examples:
Example 1
url_for :action => :index
It will link to the index action of current controller /app/controller
.
Example 2
url_for :action => :create
It will link to create action of current controller /app/controller
.
Example 3
url_for :action => :new
It will redirect to new action of current controller /app/model/new
.
Example 4
url_for :action => :show, :id => '{12}'
It will redirect to show the action of current controller with parameter ID value as 12 /app/model/{12}/show
Example 5
url_for :model => :another_model, :action => :show, :id => '{12}'
It will link to another_model
action of current controller /app/another_model/{12}/show
Example 6
url_for :controller => :another_controller, :action => :show, :id => '{12}'
It will create a link to show action of another_controller
controller /app/another_controller/{12}/show
Example 7
url_for :action => :create, :query => {:name => 'John Smith', 'address' => "http://john.smith.com"}
It will link to create action of current controller with parameter name and address:
/app/model?name=John%20Smith&address=http%3A%2F%2Fjohn.smith.com
Example 8
url_for :action => :show, :id => '{12}', :fragment => "an-anchor"
It will link to create action of current controller with a fragment an-anchor /app/model/{12}/show#an-
anchor
Digging the MVC in our application
We have seen the output but now the question that arises is how does it work? Well to know that, first we have to understand all the code generated by the Rhogen model command:
Model
The employee.rb
file in the employee folder is the model. We will write model-specific code in this file.
By default there is a class Employee generated by Rhodes generator. We can also configure a few properties of Model from this file such as:
- Type of schema—we can choose either of the two type of schema PropertyBag or Fixed schema. We will discuss this in detail in next chapter.
- Enabling Sync—this will enable the sync for the model. We will discuss this in Chapter 5.
This is the model code generated by Rhodes generator:
class Employee include Rhom::PropertyBag # Uncomment the following line to enable sync with Employee. # enable :sync #add model specifc code here end
Controller
The employee_controller.rb
file in employee folder is the controller. It has all the basic CRUD operations. The file looks like this:
require 'rho/rhocontroller' require 'helpers/browser_helper' class EmployeeController < Rho::RhoController include BrowserHelper #GET /Employee def index @employees = Employee.find(:all) render end # GET /Employee/{1} def show @employee = Employee.find(@params['id']) if @employee render :action => :show else redirect :action => :index end end # GET /Employee/new def new @employee = Employee.new render :action => :new end # GET /Employee/{1}/edit def edit @employee = Employee.find(@params['id']) if @employee render :action => :edit else redirect :action => :index end end # POST /Employee/create def create @employee = Employee.create(@params['employee']) redirect :action => :index end # POST /Employee/{1}/update def update @employee = Employee.find(@params['id']) @employee.update_attributes(@params['employee']) if @employee redirect :action => :index end # POST /Employee/{1}/delete def delete @employee = Employee.find(@params['id']) @employee.destroy if @employee redirect :action => :index end end
From the above code we understand the following points:
- Every controller in Rhodes is a sub class of RhoController
- All the CRUD operations for employee controller
- Rhodes has a unique way of interacting with database using Rhom, which we will discuss in Chapter 4
- If you are familiar with Ruby on Rails, the syntax of Rhodes controller is similar to that of Rails controller
Views
These are the .erb
files that will have basic UI stuff. You may notice that there are two types of view files .bb.erb
and .erb
files (Example: index.bb.erb
and index.erb
). The .bb.erb
files are for Blackberry and .erb
are for other phones. This is because Blackberry has limited support for HTML and CSS tags, so it uses more of the table-based user interface.
Now, we will explore the index.erb
file:
<div class="pageTitle"> <h1>Employees</h1> </div> <div class="toolbar"> <div class="leftItem regularButton"> <a href="<%= Rho::RhoConfig.start_path %>">Home</a> </div> <div class="rightItem regularButton"> <a class="button" href="<%= url_for :action => :new %>">New</a> </div> </div> <div class="content"> <ul> <% @employees.each do |employee| %> <li> <a href="<%= url_for :action => :show, :id => employee.object %>"> <span class="title"><%= employee.name %></span><span class="disclosure_indicator"></span> </a> </li> <% end %> </ul> </div>
If we see any page in view, it is divided into three parts:
- pageTitle – This code is for selecting the title of the page:
<div class="pageTitle"> <h1>Employees</h1> </div>
- toolbar – This code will generate right and left links, which will be shown on the toolbar:
<div class="toolbar"> <div class="leftItem regularButton"> <a href="<%= Rho::RhoConfig.start_path %>">Home</a> </div> <div class="rightItem regularButton"> <a class="button" href="<%= url_for :action => :new %>">New</a> </div> </div>
- content – This contains the page content that will be displayed on screen:
<div class="content"> <ul> <% @employees.each do |employee| %> <li> <a href="<%= url_for :action => :show, :id => employee.object %>"> <span class="title"><%= employee.name %></span><span class="disclosure_indicator"></span> </a> </li> <% end %> </ul> </div>
There is no strict rule that we have to divide the view in three sections. However, if we follow this it will give a native look to your application. We can design our own CSS accordingly if we want to design in some other way. But if you are using the default styling, which is generated by the Rhogen command, then we have to use this type of styling.
Rhodes configuration file—Rhoconfig.txt
Each Rhodes application contains a configuration file called rhoconfig.txt
. This file takes care of all the configurations for your application.
I am listing a few of its configurations:
- We can set up a startup page for our application by:
start_path = '/app'
- We can set the path to the options page by:
options_path = '/app/Settings'
- We can set location of bundle URL (i.e. from rhohub.com); used by desktop win32 simulator by:
rhobundle_zip_url = ''"
- We can set an optional password to access bundle (usually not required); used by desktop win32 simulator by:
rhobundle_zip_pwd = nil
- We can set Rhodes log property by MinSeverity. It decides the level of logging. 0-trace, 1-info(app level), 3-warnings, 4-errors. Make sure that for production set it to 3; otherwise it will affect your application performance.
MinSeverity = 1
- We can enable copy log messages to standard output, useful for debugging:
LogToOutput = 1
- We can set max log file size in KB, set 0 to unlimited size; when limit is reached, log wraps to beginning of file:
MaxLogFileSize=50
- We can set turn on local http server traces, off by default:
net_trace = 0
- We can set timeout of network requests in seconds (30 by default):
net_timeout = 60
- We can set where log will be posted by RhoConf.send_log:
logserver = 'http://rhologs.heroku.com'
- We can set log file prefix—contain human-readable text:
logname='helloworld'
- We can keep track of the last visited page:
KeepTrackOfLastVisitedPage = 0 LastVisitedPage = ''
- We sync server url URL by:
syncserver = 'http://localhost:9292/application'
- We can open the Rhodes app in full screen mode:
full_screen = 1
- We can set the port of the local (embedded) HTTP server. This parameter is mainly for debug purposes. If not specified, the application will use a dynamically selected one. WARNING!!! Remove this parameter before putting the application to production:
local_server_port = 8080
- We can show the status bar on Windows mobile. Its default value is 1:
wm_show_statusbar = 1
- We can disable screen rotation (enabled by default)—disable possible for ANDROID and iPhone ONLY:
disable_screen_rotation = 1
- We can disable close app when pressing back on the home screen on the Blackberry:
bb_disable_closebyback = 0
- We can load images in the background, this improves reaction speed on user actions, 0 by default:
bb_loadimages_async = 0
- We can hide the forward button and animate back button transition:
jqtouch_mode=1 splash_screen='zoom'
We can do our custom configuration also in this file. To access rhoconfig.txt
from application code, use the Rho::RhoConfig
class:
Rho::RhoConfig.full_screen Rho::RhoConfig.app_property='some value' if Rho::RhoConfig.exists?('some_property') #do something end
Building a Configuration file—build.yml
Rhodes applications contains a configuration file called build.yml
. This file takes care of the entire configuration for your application, which we need when building an application.
- We can set up the application name by:
name: <application_name>
- We can set the version number by:
version: <version_number>
- We can add the vendor name by:
vendor: <vender_name>
- We can set the location of Rhodes path from:
sdk: <sdk_location>
- We can add more Ruby libraries as an extension by:
extensions: ["extenstion_name"]
- We can specify the device SDK to be used and the also the simulator for debugging.
Changing the input style
Previously, we created our model and basic CRUD operations using the Rhogen command. Now, we will modify the HTML input form, by adding textarea, radiobuttons, etc.
Time for action – Editing view
We will customize the new.erb
and new.bb.erb
, which is responsible for creating a new employee. By default if we generate code using Rhogen all the fields in the form are textboxes. We will change these textboxes to textarea, radiobutton, and selectbox.
Follow these steps to create them:
- Replace the code for address by the following lines, which changes it to textarea:
<h4 class="groupTitle">Address</h4> <ul> <li class="textarea"> <textarea rows="5" cols="30" name= "employee[address]" > </textarea> </li> </ul>
This code will create a textarea input type as shown in this image:
- Replace the code for company with the following lines, which changes it to a select box:
<h4 class="groupTitle">Company</h4> <ul> <li> <select name="employee[company]"> <option value="Facebook" selected>Facebook</option> <option value="Twitter">Twitter</option> <option value="Google">Google</option> </select> </li> </ul>
- Replace the code for gender with the following lines, which changes it to radio buttons:
<h4 class="groupTitle">Gender</h4> <ul> <li><label for="employee[gender]">Male</label> <input type="radio" name="employee[gender]" value="male"/> </li> <li><label for="task[status]">Female</label> <input type="radio" name="employee[gender]" value="female"/> </li> </ul>
Now, we will work for blackberry and edit
new.bb.erb
. - Modifying the field Company to a select box:
<tr> <td class="itemLabel">Company: </td> <td class="itemValue"> <select name="employee[company]"> <option value="Facebook" selected>Facebook</option> <option value="Twitter">Twitter</option> <option value="Google">Google</option> </select> </td> </tr>
- Modifying the field Address to text area:
<tr> <td class="itemLabel">Address: </td> <td class="itemValue"><textarea rows="3" cols="10" name= "employee[address]" ></textarea></td> </tr> Modifying the field Gender to a radio button <tr> <td class="itemLabel">Gender: </td> <td class="itemValue"> Male <input type="radio" name="employee[gender]" value="male"/> Female <input type="radio" name="employee[gender]" value="female"/> </td> </tr>