<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ylu31</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ylu31"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Ylu31"/>
	<updated>2026-07-13T23:04:05Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96864</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96864"/>
		<updated>2015-04-23T19:41:10Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Architecture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;big&amp;gt;S1503. Sahana Eden Mobile Client&amp;lt;/big&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
This project aims at adding new functions to the EdenMobile client app to serve users better.These functions will allow mobile users to add new shelters and hospitals, get information of hospitals and shelters offline/online, get GPS location of device, and provide multilingual support.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &lt;br /&gt;
&amp;lt;ref&amp;gt;[http://eden.sahanafoundation.org/ Sahana Eden Instroduction]&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
'''Organization Registry'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;				&lt;br /&gt;
'''Project Tracking'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides a valuable tool which could tell people what are going on about the project to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Human Resources'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*There are contact lists in Sahana Eden  which can be access by users to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Inventory'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Assets'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
'''Assessments'''&amp;lt;br&amp;gt;											&lt;br /&gt;
*Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Scenarios &amp;amp; Events'''&amp;lt;br&amp;gt;&lt;br /&gt;
*To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Map'''&amp;lt;br&amp;gt;									&lt;br /&gt;
*Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Shelter Management'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Messaging'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;communication.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;controller.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;model.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;view.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mHospital.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html &amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospitalController.js (controller)&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Vehicles:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mVehicles.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehiclesController.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (controller)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An [https://docs.google.com/a/ncsu.edu/document/d/11bblC7klisYjN7Gjw6hDcs5TZ8uesJD3o2xnM2gI914/edit# overview of all the Sahana Eden projects]&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction] about the framework of Edenmobile including application design, source&amp;lt;ref&amp;gt;[http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Edenmobile Introduction]&amp;lt;/ref&amp;gt;  &lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile#J2ME list] of all the requirements need to be done in this project. &lt;br /&gt;
*An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*[https://github.com/szhao8/eden Open source code about Sahana Eden]&amp;lt;ref&amp;gt;[https://github.com/szhao8/eden Sahana Eden Github]&amp;lt;/ref&amp;gt;&lt;br /&gt;
*[https://github.com/szhao8/EdenMobile Open source code about Eden Mobile]&amp;lt;ref&amp;gt;[https://github.com/szhao8/EdenMobile EdenMobile Github]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
==Overview==&lt;br /&gt;
In this design, we add several modules to the EdenMobile client app to allow mobile users to add new shelters and hospitals. Also, users can see the list of hospitals and shelters both offline and online and we can pass users' location to the nearest medical facilities. At last, a multilingual environment is also supported.&lt;br /&gt;
==Requirements==&lt;br /&gt;
The major requirements are that:&lt;br /&gt;
*Secure login;&lt;br /&gt;
*Multiple languages;&lt;br /&gt;
*users are able to work offline, and update forms and content when online;&lt;br /&gt;
*The initial forms that will be implemented are Hospitals, and Shelters;&lt;br /&gt;
&lt;br /&gt;
==Architecture==&lt;br /&gt;
&lt;br /&gt;
Below is the overview of the Eden Mobile Platform. It uses a Model-View-Controller design pattern as the foundation of the project. And it also introduces a &amp;quot;plugin&amp;quot; mechanism, from which developers can add new modules (pages) to the main menu by adding them to &amp;quot;plugins&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Architecture.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
==Use Cases==&lt;br /&gt;
&lt;br /&gt;
* '''1. Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''2. Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''3. Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''4. Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''5. Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''6. Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* The UML use case diagram is shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Usecase.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==Add Multilanguage Support==&lt;br /&gt;
===Development-before preparation===&lt;br /&gt;
This program is hosted by a very experienced software engineering, who set the blueprint of this whole program. So we communicated with him serval times to get a better understanding of the project need and expectation. Also, he introduced the framework he used and showed some little tricky to us on google group discussion. Then we understand a mapping relationship and the implementation details about how to build a multilanguage support.&lt;br /&gt;
&lt;br /&gt;
[[File:mapping.png]]&lt;br /&gt;
&lt;br /&gt;
===Code Changes===&lt;br /&gt;
The html button changes in languages.js:&lt;br /&gt;
&lt;br /&gt;
[[File:languagesjs.png]] &lt;br /&gt;
&lt;br /&gt;
The html button changes in languagesController.js:&lt;br /&gt;
&lt;br /&gt;
[[File:languagecontroller.png]]&lt;br /&gt;
&lt;br /&gt;
Code changes in index.js:&lt;br /&gt;
&lt;br /&gt;
[[File:index.png]]&lt;br /&gt;
&lt;br /&gt;
Our basic implementation translation in controller.js function goes like this: &lt;br /&gt;
&lt;br /&gt;
[[File:basic.png]]&lt;br /&gt;
&lt;br /&gt;
languages.xml mapping information: &lt;br /&gt;
&lt;br /&gt;
[[File:xml.png]]&lt;br /&gt;
&lt;br /&gt;
===Multilanguage UI===&lt;br /&gt;
After serval times of discussion and communication, we finally realize the following UI. You can click the language you need to change to it. It's very easy-using and user comfortable. The following screenshot is what it looks like.&lt;br /&gt;
&lt;br /&gt;
After clicking the English button, the English UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:English.png]]&lt;br /&gt;
&lt;br /&gt;
After clicking the Chinese button, the Chinese UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:Chinese.png]]&lt;br /&gt;
&lt;br /&gt;
After clicking the French button, the French UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:French.png]]&lt;br /&gt;
&lt;br /&gt;
After clicking the Bosnian button, the Bosnian UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:Bosnian.png]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
&lt;br /&gt;
1. When loading Sahana Eden Mobile's main page, browser console will print the following error message:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Error1.png‎  |frame|center|underscore-min.map not found error]]&lt;br /&gt;
&lt;br /&gt;
The problem can be solved by downloading the file [https://github.com/jashkenas/underscore/blob/master/underscore-min.map underscore-min.map] and put it in the directory where underscore-min.js is stored. More information about this error can be found [http://stackoverflow.com/questions/18429625/missing-javascript-map-file-for-underscore-js-when-loading-asp-net-web-page here].&lt;br /&gt;
&lt;br /&gt;
2. When adding multi-language module to Sahana Eden Mobile's main page, browser console will print the following error message:&lt;br /&gt;
After adding a language plugin module, users can see a new button called &amp;quot;Language&amp;quot;, but it cannot be clicked and what makes worse is that the module affect other modules, for example, we cannot new a shelter. The framework is super complex and we are new here. After discussion, we write a email describing our problems to Tom Baker, the host developer, for help.&lt;br /&gt;
&lt;br /&gt;
[[File:problem.png]] &lt;br /&gt;
&lt;br /&gt;
After we received his short reply, we tried to follow his instruction to check some files but still get no idea what's our problem.&lt;br /&gt;
&lt;br /&gt;
[[File:reply.png]]&lt;br /&gt;
&lt;br /&gt;
Finally, we set breakpoints and used chrome's developer tool to help us debug. Fortunately, we found the an object is NULL, which affect the initiation. Then we found that in our controller there is a little error which leaded to this problem. After revised that, it run well now.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Usecase.png&amp;diff=96863</id>
		<title>File:S1503 Usecase.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Usecase.png&amp;diff=96863"/>
		<updated>2015-04-23T19:39:42Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: uploaded a new version of &amp;amp;quot;File:S1503 Usecase.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Architecture.png&amp;diff=96862</id>
		<title>File:S1503 Architecture.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Architecture.png&amp;diff=96862"/>
		<updated>2015-04-23T19:12:30Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: uploaded a new version of &amp;amp;quot;File:S1503 Architecture.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Architecture.png&amp;diff=96861</id>
		<title>File:S1503 Architecture.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Architecture.png&amp;diff=96861"/>
		<updated>2015-04-23T19:11:15Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96860</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96860"/>
		<updated>2015-04-23T19:10:00Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Architecture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;big&amp;gt;S1503. Sahana Eden Mobile Client&amp;lt;/big&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
This project aims at adding new functions to the EdenMobile client app to serve users better.These functions will allow mobile users to add new shelters and hospitals, get information of hospitals and shelters offline/online, get GPS location of device, and provide multilingual support.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &lt;br /&gt;
&amp;lt;ref&amp;gt;[http://eden.sahanafoundation.org/ Sahana Eden Instroduction]&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
'''Organization Registry'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;				&lt;br /&gt;
'''Project Tracking'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides a valuable tool which could tell people what are going on about the project to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Human Resources'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*There are contact lists in Sahana Eden  which can be access by users to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Inventory'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Assets'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
'''Assessments'''&amp;lt;br&amp;gt;											&lt;br /&gt;
*Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Scenarios &amp;amp; Events'''&amp;lt;br&amp;gt;&lt;br /&gt;
*To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Map'''&amp;lt;br&amp;gt;									&lt;br /&gt;
*Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Shelter Management'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Messaging'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;communication.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;controller.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;model.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;view.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mHospital.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html &amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospitalController.js (controller)&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Vehicles:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mVehicles.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehiclesController.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (controller)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An [https://docs.google.com/a/ncsu.edu/document/d/11bblC7klisYjN7Gjw6hDcs5TZ8uesJD3o2xnM2gI914/edit# overview of all the Sahana Eden projects]&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction] about the framework of Edenmobile including application design, source&amp;lt;ref&amp;gt;[http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Edenmobile Introduction]&amp;lt;/ref&amp;gt;  &lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile#J2ME list] of all the requirements need to be done in this project. &lt;br /&gt;
*An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*[https://github.com/szhao8/eden Open source code about Sahana Eden]&amp;lt;ref&amp;gt;[https://github.com/szhao8/eden Sahana Eden Github]&amp;lt;/ref&amp;gt;&lt;br /&gt;
*[https://github.com/szhao8/EdenMobile Open source code about Eden Mobile]&amp;lt;ref&amp;gt;[https://github.com/szhao8/EdenMobile EdenMobile Github]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
==Overview==&lt;br /&gt;
In this design, we add several modules to the EdenMobile client app to allow mobile users to add new shelters and hospitals. Also, users can see the list of hospitals and shelters both offline and online and we can pass users' location to the nearest medical facilities. At last, a multilingual environment is also supported.&lt;br /&gt;
==Requirements==&lt;br /&gt;
The major requirements are that:&lt;br /&gt;
*Secure login;&lt;br /&gt;
*Multiple languages;&lt;br /&gt;
*users are able to work offline, and update forms and content when online;&lt;br /&gt;
*The initial forms that will be implemented are Hospitals, and Shelters;&lt;br /&gt;
&lt;br /&gt;
==Architecture==&lt;br /&gt;
&lt;br /&gt;
Below is the overview of the Eden Mobile Platform. It uses a Model-View-Controller design pattern as the foundation of the project. And it also introduces a &amp;quot;plugin&amp;quot; mechanism for adding new features.&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Architecture.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
==Use Cases==&lt;br /&gt;
&lt;br /&gt;
* '''1. Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''2. Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''3. Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''4. Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''5. Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''6. Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* The UML use case diagram is shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Usecase.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==Add Multilanguage Support==&lt;br /&gt;
===Development-before preparation===&lt;br /&gt;
This program is hosted by a very experienced software engineering, who set the blueprint of this whole program. So we communicated with him serval times to get a better understanding of the project need and expectation. Also, he introduced the framework he used and showed some little tricky to us on google group discussion. Then we understand a mapping relationship and the implementation details about how to build a multilanguage support.&lt;br /&gt;
&lt;br /&gt;
[[File:mapping.png]]&lt;br /&gt;
&lt;br /&gt;
===Code Changes===&lt;br /&gt;
The html button changes in languages.js:&lt;br /&gt;
&lt;br /&gt;
[[File:languagesjs.png]] &lt;br /&gt;
&lt;br /&gt;
The html button changes in languagesController.js:&lt;br /&gt;
&lt;br /&gt;
[[File:languagecontroller.png]]&lt;br /&gt;
&lt;br /&gt;
Code changes in index.js:&lt;br /&gt;
&lt;br /&gt;
[[File:index.png]]&lt;br /&gt;
&lt;br /&gt;
Our basic implementation translation in controller.js function goes like this: &lt;br /&gt;
&lt;br /&gt;
[[File:basic.png]]&lt;br /&gt;
&lt;br /&gt;
languages.xml mapping information: &lt;br /&gt;
&lt;br /&gt;
[[File:xml.png]]&lt;br /&gt;
&lt;br /&gt;
===Multilanguage UI===&lt;br /&gt;
After serval times of discussion and communication, we finally realize the following UI. You can click the language you need to change to it. It's very easy-using and user comfortable. The following screenshot is what it looks like.&lt;br /&gt;
&lt;br /&gt;
After clicking the English button, the English UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:English.png]]&lt;br /&gt;
&lt;br /&gt;
After clicking the Chinese button, the Chinese UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:Chinese.png]]&lt;br /&gt;
&lt;br /&gt;
After clicking the French button, the French UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:French.png]]&lt;br /&gt;
&lt;br /&gt;
After clicking the Bosnian button, the Bosnian UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:Bosnian.png]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
&lt;br /&gt;
1. When loading Sahana Eden Mobile's main page, browser console will print the following error message:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Error1.png‎  |frame|center|underscore-min.map not found error]]&lt;br /&gt;
&lt;br /&gt;
The problem can be solved by downloading the file [https://github.com/jashkenas/underscore/blob/master/underscore-min.map underscore-min.map] and put it in the directory where underscore-min.js is stored. More information about this error can be found [http://stackoverflow.com/questions/18429625/missing-javascript-map-file-for-underscore-js-when-loading-asp-net-web-page here].&lt;br /&gt;
&lt;br /&gt;
2. When adding multi-language module to Sahana Eden Mobile's main page, browser console will print the following error message:&lt;br /&gt;
After adding a language plugin module, users can see a new button called &amp;quot;Language&amp;quot;, but it cannot be clicked and what makes worse is that the module affect other modules, for example, we cannot new a shelter. The framework is super complex and we are new here. After discussion, we write a email describing our problems to Tom Baker, the host developer, for help.&lt;br /&gt;
&lt;br /&gt;
[[File:problem.png]] &lt;br /&gt;
&lt;br /&gt;
After we received his short reply, we tried to follow his instruction to check some files but still get no idea what's our problem.&lt;br /&gt;
&lt;br /&gt;
[[File:reply.png]]&lt;br /&gt;
&lt;br /&gt;
Finally, we set breakpoints and used chrome's developer tool to help us debug. Fortunately, we found the an object is NULL, which affect the initiation. Then we found that in our controller there is a little error which leaded to this problem. After revised that, it run well now.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96859</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96859"/>
		<updated>2015-04-23T19:09:04Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Architecture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;big&amp;gt;S1503. Sahana Eden Mobile Client&amp;lt;/big&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
This project aims at adding new functions to the EdenMobile client app to serve users better.These functions will allow mobile users to add new shelters and hospitals, get information of hospitals and shelters offline/online, get GPS location of device, and provide multilingual support.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &lt;br /&gt;
&amp;lt;ref&amp;gt;[http://eden.sahanafoundation.org/ Sahana Eden Instroduction]&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
'''Organization Registry'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;				&lt;br /&gt;
'''Project Tracking'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides a valuable tool which could tell people what are going on about the project to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Human Resources'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*There are contact lists in Sahana Eden  which can be access by users to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Inventory'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Assets'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
'''Assessments'''&amp;lt;br&amp;gt;											&lt;br /&gt;
*Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Scenarios &amp;amp; Events'''&amp;lt;br&amp;gt;&lt;br /&gt;
*To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Map'''&amp;lt;br&amp;gt;									&lt;br /&gt;
*Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Shelter Management'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Messaging'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;communication.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;controller.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;model.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;view.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mHospital.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html &amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospitalController.js (controller)&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Vehicles:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mVehicles.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehiclesController.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (controller)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An [https://docs.google.com/a/ncsu.edu/document/d/11bblC7klisYjN7Gjw6hDcs5TZ8uesJD3o2xnM2gI914/edit# overview of all the Sahana Eden projects]&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction] about the framework of Edenmobile including application design, source&amp;lt;ref&amp;gt;[http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Edenmobile Introduction]&amp;lt;/ref&amp;gt;  &lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile#J2ME list] of all the requirements need to be done in this project. &lt;br /&gt;
*An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*[https://github.com/szhao8/eden Open source code about Sahana Eden]&amp;lt;ref&amp;gt;[https://github.com/szhao8/eden Sahana Eden Github]&amp;lt;/ref&amp;gt;&lt;br /&gt;
*[https://github.com/szhao8/EdenMobile Open source code about Eden Mobile]&amp;lt;ref&amp;gt;[https://github.com/szhao8/EdenMobile EdenMobile Github]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
==Overview==&lt;br /&gt;
In this design, we add several modules to the EdenMobile client app to allow mobile users to add new shelters and hospitals. Also, users can see the list of hospitals and shelters both offline and online and we can pass users' location to the nearest medical facilities. At last, a multilingual environment is also supported.&lt;br /&gt;
==Requirements==&lt;br /&gt;
The major requirements are that:&lt;br /&gt;
*Secure login;&lt;br /&gt;
*Multiple languages;&lt;br /&gt;
*users are able to work offline, and update forms and content when online;&lt;br /&gt;
*The initial forms that will be implemented are Hospitals, and Shelters;&lt;br /&gt;
&lt;br /&gt;
==Architecture==&lt;br /&gt;
&lt;br /&gt;
Below is the overview of the Eden Mobile Platform. It uses a Model-View-Controller design pattern as the foundation of the project. And it also introduces a &amp;quot;plugin&amp;quot; mechanism for adding new features.&lt;br /&gt;
[[File:architecture.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Use Cases==&lt;br /&gt;
&lt;br /&gt;
* '''1. Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''2. Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''3. Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''4. Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''5. Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''6. Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* The UML use case diagram is shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Usecase.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==Add Multilanguage Support==&lt;br /&gt;
===Development-before preparation===&lt;br /&gt;
This program is hosted by a very experienced software engineering, who set the blueprint of this whole program. So we communicated with him serval times to get a better understanding of the project need and expectation. Also, he introduced the framework he used and showed some little tricky to us on google group discussion. Then we understand a mapping relationship and the implementation details about how to build a multilanguage support.&lt;br /&gt;
&lt;br /&gt;
[[File:mapping.png]]&lt;br /&gt;
&lt;br /&gt;
===Code Changes===&lt;br /&gt;
The html button changes in languages.js:&lt;br /&gt;
&lt;br /&gt;
[[File:languagesjs.png]] &lt;br /&gt;
&lt;br /&gt;
The html button changes in languagesController.js:&lt;br /&gt;
&lt;br /&gt;
[[File:languagecontroller.png]]&lt;br /&gt;
&lt;br /&gt;
Code changes in index.js:&lt;br /&gt;
&lt;br /&gt;
[[File:index.png]]&lt;br /&gt;
&lt;br /&gt;
Our basic implementation translation in controller.js function goes like this: &lt;br /&gt;
&lt;br /&gt;
[[File:basic.png]]&lt;br /&gt;
&lt;br /&gt;
languages.xml mapping information: &lt;br /&gt;
&lt;br /&gt;
[[File:xml.png]]&lt;br /&gt;
&lt;br /&gt;
===Multilanguage UI===&lt;br /&gt;
After serval times of discussion and communication, we finally realize the following UI. You can click the language you need to change to it. It's very easy-using and user comfortable. The following screenshot is what it looks like.&lt;br /&gt;
&lt;br /&gt;
After clicking the English button, the English UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:English.png]]&lt;br /&gt;
&lt;br /&gt;
After clicking the Chinese button, the Chinese UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:Chinese.png]]&lt;br /&gt;
&lt;br /&gt;
After clicking the French button, the French UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:French.png]]&lt;br /&gt;
&lt;br /&gt;
After clicking the Bosnian button, the Bosnian UI shows as following:&lt;br /&gt;
&lt;br /&gt;
[[File:Bosnian.png]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
&lt;br /&gt;
1. When loading Sahana Eden Mobile's main page, browser console will print the following error message:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Error1.png‎  |frame|center|underscore-min.map not found error]]&lt;br /&gt;
&lt;br /&gt;
The problem can be solved by downloading the file [https://github.com/jashkenas/underscore/blob/master/underscore-min.map underscore-min.map] and put it in the directory where underscore-min.js is stored. More information about this error can be found [http://stackoverflow.com/questions/18429625/missing-javascript-map-file-for-underscore-js-when-loading-asp-net-web-page here].&lt;br /&gt;
&lt;br /&gt;
2. When adding multi-language module to Sahana Eden Mobile's main page, browser console will print the following error message:&lt;br /&gt;
After adding a language plugin module, users can see a new button called &amp;quot;Language&amp;quot;, but it cannot be clicked and what makes worse is that the module affect other modules, for example, we cannot new a shelter. The framework is super complex and we are new here. After discussion, we write a email describing our problems to Tom Baker, the host developer, for help.&lt;br /&gt;
&lt;br /&gt;
[[File:problem.png]] &lt;br /&gt;
&lt;br /&gt;
After we received his short reply, we tried to follow his instruction to check some files but still get no idea what's our problem.&lt;br /&gt;
&lt;br /&gt;
[[File:reply.png]]&lt;br /&gt;
&lt;br /&gt;
Finally, we set breakpoints and used chrome's developer tool to help us debug. Fortunately, we found the an object is NULL, which affect the initiation. Then we found that in our controller there is a little error which leaded to this problem. After revised that, it run well now.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Error1.png&amp;diff=96643</id>
		<title>File:S1503 Error1.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Error1.png&amp;diff=96643"/>
		<updated>2015-04-13T00:34:08Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96642</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96642"/>
		<updated>2015-04-13T00:33:56Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;big&amp;gt;S1503. Sahana Eden Mobile Client&amp;lt;/big&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
This project aims at adding new functions to the EdenMobile client app to serve users better.These functions will allow mobile users to add new shelters and hospitals, get information of hospitals and shelters offline/online, get GPS location of device, and provide multilingual support.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &lt;br /&gt;
&amp;lt;ref&amp;gt;[http://eden.sahanafoundation.org/ Sahana Eden Instroduction]&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
'''Organization Registry'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;				&lt;br /&gt;
'''Project Tracking'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides a valuable tool which could tell people what are going on about the project to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Human Resources'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*There are contact lists in Sahana Eden  which can be access by users to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Inventory'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Assets'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
'''Assessments'''&amp;lt;br&amp;gt;											&lt;br /&gt;
*Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Scenarios &amp;amp; Events'''&amp;lt;br&amp;gt;&lt;br /&gt;
*To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Map'''&amp;lt;br&amp;gt;									&lt;br /&gt;
*Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Shelter Management'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Messaging'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;communication.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;controller.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;model.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;view.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mHospital.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html &amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospitalController.js (controller)&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Vehicles:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mVehicles.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehiclesController.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (controller)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An [https://docs.google.com/a/ncsu.edu/document/d/11bblC7klisYjN7Gjw6hDcs5TZ8uesJD3o2xnM2gI914/edit# overview of all the Sahana Eden projects]&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction] about the framework of Edenmobile including application design, source&amp;lt;ref&amp;gt;[http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Edenmobile Introduction]&amp;lt;/ref&amp;gt;  &lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile#J2ME list] of all the requirements need to be done in this project. &lt;br /&gt;
*An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*[https://github.com/szhao8/eden Open source code about Sahana Eden]&amp;lt;ref&amp;gt;[https://github.com/szhao8/eden Sahana Eden Github]&amp;lt;/ref&amp;gt;&lt;br /&gt;
*[https://github.com/szhao8/EdenMobile Open source code about Eden Mobile]&amp;lt;ref&amp;gt;[https://github.com/szhao8/EdenMobile EdenMobile Github]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
==Overview==&lt;br /&gt;
In this design, we add several modules to the EdenMobile client app to allow mobile users to add new shelters and hospitals. Also, users can see the list of hospitals and shelters both offline and online and we can pass users' location to the nearest medical facilities. At last, a multilingual environment is also supported.&lt;br /&gt;
==Requirements==&lt;br /&gt;
The major requirements are that:&lt;br /&gt;
*Secure login;&lt;br /&gt;
*Multiple languages;&lt;br /&gt;
*users are able to work offline, and update forms and content when online;&lt;br /&gt;
*The initial forms that will be implemented are Hospitals, and Shelters;&lt;br /&gt;
&lt;br /&gt;
==Architecture==&lt;br /&gt;
==Use Cases==&lt;br /&gt;
&lt;br /&gt;
* '''1. Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''2. Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''3. Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''4. Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''5. Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''6. Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* The UML use case diagram is shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Usecase.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
&lt;br /&gt;
1. When loading Sahana Eden Mobile's main page, browser console will print the following error message:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Error1.png‎  |frame|center|underscore-min.map not found error]]&lt;br /&gt;
&lt;br /&gt;
The problem can be solved by downloading the file [https://github.com/jashkenas/underscore/blob/master/underscore-min.map underscore-min.map] and put it in the directory where underscore-min.js is stored. More information about this error can be found [http://stackoverflow.com/questions/18429625/missing-javascript-map-file-for-underscore-js-when-loading-asp-net-web-page here].&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96475</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96475"/>
		<updated>2015-04-02T03:49:39Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Scope */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;big&amp;gt;S1503. Sahana Eden Mobile Client&amp;lt;/big&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
This project aims at adding new functions to the EdenMobile client app to serve users better.These functions will allow mobile users to add new shelters and hospitals, get information of hospitals and shelters offline/online, get GPS location of device, and provide multilingual support.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
'''Organization Registry'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;				&lt;br /&gt;
'''Project Tracking'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides a valuable tool which could tell people what are going on about the project to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Human Resources'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*There are contact lists in Sahana Eden  which can be access by users to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Inventory'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Assets'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
'''Assessments'''&amp;lt;br&amp;gt;											&lt;br /&gt;
*Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Scenarios &amp;amp; Events'''&amp;lt;br&amp;gt;&lt;br /&gt;
*To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Map'''&amp;lt;br&amp;gt;									&lt;br /&gt;
*Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Shelter Management'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Messaging'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;communication.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;controller.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;model.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;view.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mHospital.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html &amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospitalController.js (controller)&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Vehicles:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mVehicles.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehiclesController.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (controller)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction] about the framework of Edenmobile including application design, source  &lt;br /&gt;
* [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Source code]&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
==Overview==&lt;br /&gt;
In this design, we add several modules to the EdenMobile client app to allow mobile users to add new shelters and hospitals. Also, users can see the list of hospitals and shelters both offline and online and we can pass users' location to the nearest medical facilities. At last, a multilingual environment is also supported.&lt;br /&gt;
==Requirements==&lt;br /&gt;
The major requirements are that:&lt;br /&gt;
*Secure login;&lt;br /&gt;
*Multiple languages;&lt;br /&gt;
*users are able to work offline, and update forms and content when online;&lt;br /&gt;
*The initial forms that will be implemented are Hospitals, and Shelters;&lt;br /&gt;
&lt;br /&gt;
==Architecture==&lt;br /&gt;
==Use Cases==&lt;br /&gt;
&lt;br /&gt;
* '''1. Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''2. Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''3. Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''4. Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''5. Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''6. Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* The UML use case diagram is shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Usecase.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshoots=&lt;br /&gt;
=References=&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96474</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96474"/>
		<updated>2015-04-02T03:35:57Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Purpose */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;big&amp;gt;S1503. Sahana Eden Mobile Client&amp;lt;/big&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
This project aims at adding new functions to the EdenMobile client app to serve users better.These functions will allow mobile users to add new shelters and hospitals, get information of hospitals and shelters offline/online, get GPS location of device, and provide multilingual support.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
'''Organization Registry'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;				&lt;br /&gt;
'''Project Tracking'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides a valuable tool which could tell people what are going on about the project to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Human Resources'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*There are contact lists in Sahana Eden  which can be access by users to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Inventory'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Assets'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
'''Assessments'''&amp;lt;br&amp;gt;											&lt;br /&gt;
*Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Scenarios &amp;amp; Events'''&amp;lt;br&amp;gt;&lt;br /&gt;
*To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Map'''&amp;lt;br&amp;gt;									&lt;br /&gt;
*Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Shelter Management'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Messaging'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;communication.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;controller.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;model.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;view.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mHospital.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html &amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospitalController.js (controller)&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Vehicles:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mVehicles.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehiclesController.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (controller)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction] about the framework of Edenmobile including application design, source  &lt;br /&gt;
* [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Source code]&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
==Overview==&lt;br /&gt;
In this design, we add several modules to the EdenMobile client app to allow mobile users to add new shelters and hospitals. Also, users can see the list of hospitals and shelters both offline and online and we can pass users' location to the nearest medical facilities. At last, a multilingual environment is also supported.&lt;br /&gt;
==Requirements==&lt;br /&gt;
The major requirements are that:&lt;br /&gt;
*Secure login;&lt;br /&gt;
*Multiple languages;&lt;br /&gt;
*users are able to work offline, and update forms and content when online;&lt;br /&gt;
*The initial forms that will be implemented are Hospitals, and Shelters;&lt;br /&gt;
&lt;br /&gt;
==Architecture==&lt;br /&gt;
==Use Cases==&lt;br /&gt;
&lt;br /&gt;
* '''1. Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''2. Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''3. Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''4. Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''5. Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''6. Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* The UML use case diagram is shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Usecase.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshoots=&lt;br /&gt;
=References=&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96470</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96470"/>
		<updated>2015-04-02T01:54:41Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;big&amp;gt;S1503. Sahana Eden Mobile Client&amp;lt;/big&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
This project is aimed at adding new functions to the EdenMobile client app to serve users better.These functions will allow mobile users to realize functions like&lt;br /&gt;
adding new shelters and hospitals, observing the list of hospitals and shelters both offline and online ,passing users' location to the nearest medical facilities and realizing a multilingual environment. &lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
'''Organization Registry'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;				&lt;br /&gt;
'''Project Tracking'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides a valuable tool which could tell people what are going on about the project to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Human Resources'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*There are contact lists in Sahana Eden  which can be access by users to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Inventory'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Assets'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
'''Assessments'''&amp;lt;br&amp;gt;											&lt;br /&gt;
*Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Scenarios &amp;amp; Events'''&amp;lt;br&amp;gt;&lt;br /&gt;
*To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Map'''&amp;lt;br&amp;gt;									&lt;br /&gt;
*Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Shelter Management'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Messaging'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;communication.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;controller.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;model.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;view.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mHospital.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html &amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospitalController.js (controller)&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Vehicles:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mVehicles.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehiclesController.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (controller)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction] about the framework of Edenmobile including application design, source  &lt;br /&gt;
* [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Source code]&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
==Overview==&lt;br /&gt;
In this design, we add several modules to the EdenMobile client app to allow mobile users to add new shelters and hospitals. Also, users can see the list of hospitals and shelters both offline and online and we can pass users' location to the nearest medical facilities. At last, a multilingual environment is also supported.&lt;br /&gt;
==Requirements==&lt;br /&gt;
The major requirements are that:&lt;br /&gt;
*Secure login;&lt;br /&gt;
*Multiple languages;&lt;br /&gt;
*users are able to work offline, and update forms and content when online;&lt;br /&gt;
*The initial forms that will be implemented are Hospitals, and Shelters;&lt;br /&gt;
&lt;br /&gt;
==Architecture==&lt;br /&gt;
==Use Cases==&lt;br /&gt;
&lt;br /&gt;
* '''1. Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''2. Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''3. Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''4. Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''5. Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''6. Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* The UML use case diagram is shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Usecase.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshoots=&lt;br /&gt;
=References=&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Usecase.png&amp;diff=96427</id>
		<title>File:S1503 Usecase.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Usecase.png&amp;diff=96427"/>
		<updated>2015-04-02T00:25:24Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: uploaded a new version of &amp;amp;quot;File:S1503 Usecase.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96314</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96314"/>
		<updated>2015-04-01T02:29:40Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Use Case */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;big&amp;gt;S1503. JavaRosa Mobile Client&amp;lt;/big&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
This project is aimed at adding new functions to the EdenMobile client app to serve users better.These functions will allow mobile users to realize functions like&lt;br /&gt;
adding new shelters and hospitals, observing the list of hospitals and shelters both offline and online ,passing users' location to the nearest medical facilities and realizing a multilingual environment. &lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
'''Organization Registry'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;				&lt;br /&gt;
'''Project Tracking'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides a valuable tool which could tell people what are going on about the project to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Human Resources'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*There are contact lists in Sahana Eden  which can be access by users to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Inventory'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Assets'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
'''Assessments'''&amp;lt;br&amp;gt;											&lt;br /&gt;
*Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Scenarios &amp;amp; Events'''&amp;lt;br&amp;gt;&lt;br /&gt;
*To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Map'''&amp;lt;br&amp;gt;									&lt;br /&gt;
*Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Shelter Management'''&amp;lt;br&amp;gt;	&lt;br /&gt;
*When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Messaging'''&amp;lt;br&amp;gt;&lt;br /&gt;
*Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;communication.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;controller.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;model.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;view.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mHospital.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html &amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospitalController.js (controller)&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Vehicles:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mVehicles.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehiclesController.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (controller)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction] about the framework of Edenmobile including application design, source  &lt;br /&gt;
* [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Source code]&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
==Overview==&lt;br /&gt;
In this design, we add several modules to the EdenMobile client app to allow mobile users to add new shelters and hospitals. Also, users can see the list of hospitals and shelters both offline and online and we can pass users' location to the nearest medical facilities. At last, a multilingual environment is also supported.&lt;br /&gt;
==Requirements==&lt;br /&gt;
The major requirements are that:&lt;br /&gt;
*Secure login;&lt;br /&gt;
*Multiple languages;&lt;br /&gt;
*users are able to work offline, and update forms and content when online;&lt;br /&gt;
*The initial forms that will be implemented are Hospitals, and Shelters;&lt;br /&gt;
&lt;br /&gt;
==Architecture==&lt;br /&gt;
==Use Cases==&lt;br /&gt;
&lt;br /&gt;
* '''1. Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''2. Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''3. Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''4. Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''5. Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* '''6. Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* The UML use case diagram is shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Usecase.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshoots=&lt;br /&gt;
=References=&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96289</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96289"/>
		<updated>2015-04-01T02:17:12Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* What does Sahana Eden do? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;big&amp;gt;S1503. JavaRosa Mobile Client&amp;lt;/big&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
This project is aimed at adding new functions to the EdenMobile client app to serve users better.These functions will allow mobile users to realize functions like&lt;br /&gt;
adding new shelters and hospitals, observing the list of hospitals and shelters both offline and online ,passing users' location to the nearest medical facilities and realizing a multilingual environment. &lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;communication.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;controller.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;model.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;view.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mHospital.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html &amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;hospitalController.js (controller)&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Vehicles:&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;mVehicles.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (model)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (views)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;vehiclesController.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; (controller)&lt;br /&gt;
*&amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;config.js&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
*'''Organization Registry'''	&amp;lt;br&amp;gt;	&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;				&lt;br /&gt;
'''Project Tracking'''&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; Sahana Eden provides a valuable tool which could tell people what are going on about the project to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Human Resources'''&amp;lt;br&amp;gt;	&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; There are contact lists in Sahana Eden  which can be access by users to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Inventory'''&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Assets'''&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
'''Assessments'''&amp;lt;br&amp;gt;											&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Scenarios &amp;amp; Events'''&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Map'''&amp;lt;br&amp;gt;									&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
'''Shelter Management'''&amp;lt;br&amp;gt;	&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Messaging'''&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction] about the framework of Edenmobile including application design, source  &lt;br /&gt;
* [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Source code]&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
==Overview==&lt;br /&gt;
In this design, we add several modules to the EdenMobile client app to allow mobile users to add new shelters and hospitals. Also, users can see the list of hospitals and shelters both offline and online and we can pass users' location to the nearest medical facilities. At last, a multilingual environment is also supported.&lt;br /&gt;
==Requirements==&lt;br /&gt;
The major requirements are that:&lt;br /&gt;
*Secure login;&lt;br /&gt;
*Multiple languages;&lt;br /&gt;
*users are able to work offline, and update forms and content when online;&lt;br /&gt;
*The initial forms that will be implemented are Hospitals, and Shelters;&lt;br /&gt;
&lt;br /&gt;
==Architecture==&lt;br /&gt;
=='''Use Case'''==&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #1: Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #2: Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #3: Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #4: Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #5: Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #6: Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* The UML use case diagram is shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Usecase.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshoots=&lt;br /&gt;
=References=&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Usecase.png&amp;diff=96244</id>
		<title>File:S1503 Usecase.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Usecase.png&amp;diff=96244"/>
		<updated>2015-04-01T01:56:35Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: uploaded a new version of &amp;amp;quot;File:S1503 Usecase.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Usecase.png&amp;diff=96234</id>
		<title>File:S1503 Usecase.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Usecase.png&amp;diff=96234"/>
		<updated>2015-04-01T01:45:22Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: uploaded a new version of &amp;amp;quot;File:S1503 Usecase.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96233</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96233"/>
		<updated>2015-04-01T01:44:16Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Use Case */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;big&amp;gt;S1503. JavaRosa Mobile Client&amp;lt;/big&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
This project is aimed at adding new functions to the EdenMobile client app to serve users better.These functions will allow mobile users to realize functions like&lt;br /&gt;
adding new shelters and hospitals, observing the list of hospitals and shelters both offline and online ,passing users' location to the nearest medical facilities and realizing a multilingual environment. &lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files&lt;br /&gt;
*communication.js&lt;br /&gt;
*controller.js&lt;br /&gt;
*model.js&lt;br /&gt;
*view.js&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*mHospital.js (model)&lt;br /&gt;
*hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html (views)&lt;br /&gt;
*hospitalController.js (controller)&lt;br /&gt;
*config.js(Giving details on the configuration of the plugin)&lt;br /&gt;
Vehicles:&lt;br /&gt;
*mVehicles.js (model)&lt;br /&gt;
*vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html (views)&lt;br /&gt;
*vehiclesController.js (controller)&lt;br /&gt;
*config.js(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
===Organization Registry===			&lt;br /&gt;
Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;						&lt;br /&gt;
====Project Tracking====&lt;br /&gt;
Sahana Eden provides a valuable tool which could tell people what are going on about the project to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
====Human Resources====		&lt;br /&gt;
There are contact lists in Sahana Eden  which can be access by users to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
====Inventory====		&lt;br /&gt;
Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
====Assets====&lt;br /&gt;
Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
====Assessments====											&lt;br /&gt;
Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
====Scenarios &amp;amp; Events====&lt;br /&gt;
To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
====Map	====									&lt;br /&gt;
Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
====Shelter Management====		&lt;br /&gt;
When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
====Messaging====&lt;br /&gt;
Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An &amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;[https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion]&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;, explaining former problems developers met and corresponding solutions&lt;br /&gt;
*An &amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;[http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction]&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt; about the framework of Edenmobile including application design, source  &lt;br /&gt;
* &amp;lt;strong&amp;gt;&amp;lt;i&amp;gt;[http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Source code]&amp;lt;/i&amp;gt;&amp;lt;/strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
===Overview===&lt;br /&gt;
In this design, we add several modules to the EdenMobile client app to allow mobile users to add new shelters and hospitals. Also, users can see the list of hospitals and shelters both offline and online and we can pass users' location to the nearest medical facilities. At last, a multilingual environment is also supported.&lt;br /&gt;
===Requirements===&lt;br /&gt;
The major requirements are that:&lt;br /&gt;
*Secure login;&lt;br /&gt;
*Multiple languages;&lt;br /&gt;
*users are able to work offline, and update forms and content when online;&lt;br /&gt;
*The initial forms that will be implemented are Hospitals, and Shelters;&lt;br /&gt;
&lt;br /&gt;
===Architecture===&lt;br /&gt;
=='''Use Case'''==&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #1: Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #2: Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #3: Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #4: Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #5: Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #6: Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* The UML use case diagram is shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:S1503_Usecase.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshoots=&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Usecase.png&amp;diff=96231</id>
		<title>File:S1503 Usecase.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:S1503_Usecase.png&amp;diff=96231"/>
		<updated>2015-04-01T01:42:30Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96214</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96214"/>
		<updated>2015-04-01T01:07:59Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Use Case */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;big&amp;gt;E1526. JavaRosa Mobile Client&amp;lt;/big&amp;gt;&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
To add several modules to the EdenMobile client app based on the web2py framework to allow mobile users to add new shelters and hospitals,  to see the list of hospitals and shelters both offline and online ,pass users' location to the nearest medical facilities and realize a multilingual environment. &lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files&lt;br /&gt;
*communication.js&lt;br /&gt;
*controller.js&lt;br /&gt;
*model.js&lt;br /&gt;
*view.js&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*mHospital.js (model)&lt;br /&gt;
*hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html (views)&lt;br /&gt;
*hospitalController.js (controller)&lt;br /&gt;
*config.js(Giving details on the configuration of the plugin&lt;br /&gt;
Vehicles:&lt;br /&gt;
*mVehicles.js (model)&lt;br /&gt;
*vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html (views)&lt;br /&gt;
*vehiclesController.js (controller)&lt;br /&gt;
*config.js(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
===Organization Registry===			&lt;br /&gt;
Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;						&lt;br /&gt;
====Project Tracking====&lt;br /&gt;
By telling you Who’s Doing What, Where, and When, Sahana Eden provides a valuable tool to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
====Human Resources====		&lt;br /&gt;
Sahana Eden can also be used to provide a contact list to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
====Inventory====		&lt;br /&gt;
Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
====Assets====&lt;br /&gt;
Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
====Assessments====											&lt;br /&gt;
Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
====Scenarios &amp;amp; Events====&lt;br /&gt;
To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
====Map	====									&lt;br /&gt;
Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
====Shelter Management====		&lt;br /&gt;
When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
====Messaging====&lt;br /&gt;
Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
*An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction] about the framework of Edenmobile including application design, source  &lt;br /&gt;
* [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework Source code]&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
=='''Use Case'''==&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #1: Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #2: Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #3: Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #4: Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #5: Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #6: Multi-Language Support '''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Choose a language from settings page&lt;br /&gt;
&lt;br /&gt;
[[File:TO_BE_ADDED.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshoots=&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96208</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96208"/>
		<updated>2015-04-01T01:00:32Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Use Case */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;big&amp;gt;E1526. JavaRosa Mobile Client&amp;lt;/big&amp;gt;&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
To add several modules to the EdenMobile client app based on the web2py framework to allow mobile users to add new shelters and hospitals,  to see the list of hospitals and shelters both offline and online ,pass users' location to the nearest medical facilities and realize a multilingual environment. &lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files&lt;br /&gt;
*communication.js&lt;br /&gt;
*controller.js&lt;br /&gt;
*model.js&lt;br /&gt;
*view.js&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*mHospital.js (model)&lt;br /&gt;
*hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html (views)&lt;br /&gt;
*hospitalController.js (controller)&lt;br /&gt;
*config.js(Giving details on the configuration of the plugin&lt;br /&gt;
Vehicles:&lt;br /&gt;
*mVehicles.js (model)&lt;br /&gt;
*vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html (views)&lt;br /&gt;
*vehiclesController.js (controller)&lt;br /&gt;
*config.js(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
===Organization Registry===			&lt;br /&gt;
Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;						&lt;br /&gt;
====Project Tracking====&lt;br /&gt;
By telling you Who’s Doing What, Where, and When, Sahana Eden provides a valuable tool to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
====Human Resources====		&lt;br /&gt;
Sahana Eden can also be used to provide a contact list to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
====Inventory====		&lt;br /&gt;
Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
====Assets====&lt;br /&gt;
Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
====Assessments====											&lt;br /&gt;
Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
====Scenarios &amp;amp; Events====&lt;br /&gt;
To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
====Map	====									&lt;br /&gt;
Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
====Shelter Management====		&lt;br /&gt;
When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
====Messaging====&lt;br /&gt;
Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
* An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction about the framework of Edenmobile including application design, source ] &lt;br /&gt;
Source code&lt;br /&gt;
http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
=='''Use Case'''==&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #1: Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #2: Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #3: Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #4: Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Student finish work for first round&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #5: Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Student not finish work for first round&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:TO_BE_ADDED.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshoots=&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96206</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96206"/>
		<updated>2015-04-01T00:59:56Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Use Case */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;big&amp;gt;E1526. JavaRosa Mobile Client&amp;lt;/big&amp;gt;&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
To add several modules to the EdenMobile client app based on the web2py framework to allow mobile users to add new shelters and hospitals,  to see the list of hospitals and shelters both offline and online and pass their location to the nearest medical facilities. &lt;br /&gt;
==Scope==&lt;br /&gt;
We will realize the signup, secure login and logout function, which would add new module into the following files&lt;br /&gt;
*communication.js&lt;br /&gt;
*controller.js&lt;br /&gt;
*model.js&lt;br /&gt;
*view.js&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
*mHospital.js (model)&lt;br /&gt;
*hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html (views)&lt;br /&gt;
*hospitalController.js (controller)&lt;br /&gt;
*config.js(Giving details on the configuration of the plugin&lt;br /&gt;
Vehicles:&lt;br /&gt;
*mVehicles.js (model)&lt;br /&gt;
*vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html (views)&lt;br /&gt;
*vehiclesController.js (controller)&lt;br /&gt;
*config.js(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What does Sahana Eden do?=== 							&lt;br /&gt;
Sahana Eden provides various of functions which are sorted in several different modules.&amp;lt;br&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
===Organization Registry===			&lt;br /&gt;
Sahana Eden’s Organization Registry can track what organizations do and organizations also could record their Offices, Warehouse and Field Sites including their locations so they can be mapped as well as links to other modules such as Human Resources, Assets and Inventory.&amp;lt;br&amp;gt;						&lt;br /&gt;
====Project Tracking====&lt;br /&gt;
By telling you Who’s Doing What, Where, and When, Sahana Eden provides a valuable tool to help organizations responding to disasters know where the greatest needs are and coordinate with others who are engaged in similar work.&amp;lt;br&amp;gt;&lt;br /&gt;
====Human Resources====		&lt;br /&gt;
Sahana Eden can also be used to provide a contact list to ensure that the right people can be contacted at the right time.&amp;lt;br&amp;gt;&lt;br /&gt;
====Inventory====		&lt;br /&gt;
Sahana Eden can be used to manage inventories of items and match requests for items with warehouses and other facilities which have them available. Sahana Eden can support multiple Catalogs of Items as well as providing alternative items to ensure more effective use of supplies. &amp;lt;br&amp;gt;&lt;br /&gt;
====Assets====&lt;br /&gt;
Sahana Eden is able to manage assets which are needed to respond to disasters, track where they are, who they have been assigned to, and what condition they are in. This ensures that assets are used effectively and efficiently.	&amp;lt;br&amp;gt;&lt;br /&gt;
====Assessments====											&lt;br /&gt;
Sahana Eden can be used to collect and analyze information from assessments to help organizations more effectively plan their disaster management activities. &amp;lt;br&amp;gt;&lt;br /&gt;
====Scenarios &amp;amp; Events====&lt;br /&gt;
To help organizations better plan for disasters, Sahana Eden can be used to plan for different scenarios, including recording what human resources, assets, facilities and tasks will be needed to effectively respond.&amp;lt;br&amp;gt;&lt;br /&gt;
====Map	====									&lt;br /&gt;
Sahana Eden has fully integrated mapping functionality which allows any location-based data to be visualized on a map. Maps provide situational awareness which is essential when either planning to prepare for or respond to a disaster.&amp;lt;br&amp;gt;&lt;br /&gt;
====Shelter Management====		&lt;br /&gt;
When disasters are widespread and result in population displacement, understanding and tracking the landscape of shelters - and the people in them - is a critical activity. The Shelter Registry provides functionality to list and track information on shelters and on the people arriving and departing. &amp;lt;br&amp;gt;&lt;br /&gt;
====Messaging====&lt;br /&gt;
Sahana Eden provides support for messages to be sent to one or Distribution Groups by Email, SMS, Twitter and Google Talk. Interactive messages can also be set up to allow people to send short message queries to Sahana Eden and receive automatic responses.&amp;lt;br&amp;gt;&lt;br /&gt;
===Sahana Eden Architecture===&lt;br /&gt;
The basic Sahana Eden architecture is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 100%; border: 1px dotted rgb(0, 0, 0); border-collapse: collapse;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Server&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Apache&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Other web servers can also be used, such as Cherokee.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Application&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Sahana Eden&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Web Application Framework&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Web2Py&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Programming Language&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Python &amp;amp;amp; Java Script&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Database&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;MySQL, PostgreSQL, or SQLite&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;p&amp;gt;MySQL, PostgreSQL, and SQLite are supported.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Other databases should be usable without major additional work since Web2Py supplies many connectors.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Operating System&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Linux (Debian recommended)&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border: 1px dotted rgb(0, 0, 0);&amp;quot;&amp;gt;Windows and Mac OS X are possible, but only recommended for single-user environments.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
former developer discussion about Sahana Oden &lt;br /&gt;
* An [https://groups.google.com/forum/?utm_medium=email&amp;amp;utm_source=footer#!forum/sahana-eden google discussion], explaining former problems developers met and corresponding solutions&lt;br /&gt;
*An [http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework basic introduction about the framework of Edenmobile including application design, source ] &lt;br /&gt;
Source code&lt;br /&gt;
http://eden.sahanafoundation.org/wiki/BluePrint/Mobile/EdenMobileFramework&lt;br /&gt;
&lt;br /&gt;
=Design=&lt;br /&gt;
=='''Use Case'''==&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #1: Security Log in'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills login form, which includes username, password and Captcha code.&lt;br /&gt;
*** Submit form to Sahana Server.&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #2: Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to Sahana Server.&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #3: Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User fills forms of shelter/warehouse/disaster etc.&lt;br /&gt;
*** Submit form to local database.&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #4: Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Student finish work for first round&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Download new forms from server&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #5: Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Student not finish work for first round&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** Synchronize local data with server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:TO_BE_ADDED.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshoots=&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96199</id>
		<title>CSC/ECE 517 Spring 2015 S1503 LWJZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_S1503_LWJZ&amp;diff=96199"/>
		<updated>2015-04-01T00:47:53Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Use Cases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;big&amp;gt;E1526. JavaRosa Mobile Client&amp;lt;/big&amp;gt;&lt;br /&gt;
=Introduction=&lt;br /&gt;
==Purpose==&lt;br /&gt;
To add several modules to the EdenMobile client app based on the web2py framework to allow mobile users to add new shelters and hospitals,  to see the list of hospitals and shelters both offline and online and pass their location to the nearest medical facilities. &lt;br /&gt;
==Scope==&lt;br /&gt;
 We will realize the signup, secure login and logout function, which would add new module into the following files:&lt;br /&gt;
           communication.js&lt;br /&gt;
           controller.js&lt;br /&gt;
           model.js&lt;br /&gt;
           view.js&lt;br /&gt;
We will make it available in multiple languages environment which will implement the languages fold.&lt;br /&gt;
We will add some new items including:“ hospital”, “vehicles” which will be added into the folder named “plugins”. The following file will be added into their corrsponding folders:&amp;lt;br&amp;gt;&lt;br /&gt;
Hospitals:&lt;br /&gt;
              mHospital.js (model)&lt;br /&gt;
              hospital.js, editHospital.js, hospital.html, hospital.css, editHospital.html (views)&lt;br /&gt;
              hospitalController.js (controller)&lt;br /&gt;
              config.js(Giving details on the configuration of the plugin&lt;br /&gt;
Vehicles:&lt;br /&gt;
              mVehicles.js (model)&lt;br /&gt;
              vehicles.js, editVehicles.js, vehicles.html, vehicles.css, editVehicles.html (views)&lt;br /&gt;
              vehiclesController.js (controller)&lt;br /&gt;
              config.js(Giving details on the configuration of the plugin)&lt;br /&gt;
Also, we find some bugs and eliminate them. These could be any possible file in this project.&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
===What’s Sahana Eden?=== &lt;br /&gt;
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. It is the latest evolution of Sahana Software which was initially developed by members of the information technology (IT) community in Sri Lanka to provide solutions for the relief effort following the 2004 Indian Ocean Tsunami. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
=Design=&lt;br /&gt;
=='''Use Case'''==&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #1: Submit forms to server'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** User logs in to Sahana Server.&lt;br /&gt;
*** User fills .&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #2: Submit forms to local storage'''&lt;br /&gt;
** '''Actor:''' Mobile App User&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** A.&lt;br /&gt;
*** B.&lt;br /&gt;
*** C.&lt;br /&gt;
*** D.&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #3: Download new forms from server'''&lt;br /&gt;
** '''Actor:''' Student finish work for first round&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** A.&lt;br /&gt;
*** B.&lt;br /&gt;
*** C.&lt;br /&gt;
*** D.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case #4: Synchronize local data with server '''&lt;br /&gt;
** '''Actor:''' Student not finish work for first round&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** A.&lt;br /&gt;
*** B.&lt;br /&gt;
*** C.&lt;br /&gt;
*** D.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:TO_BE_ADDED.png‎  |frame|center|Use Case Diagram]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshoots=&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95399</id>
		<title>CSC/ECE 517 Spring 2015/oss E1506 SYZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95399"/>
		<updated>2015-03-22T15:35:46Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Change Rails 2 syntax to Rails 4 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;E1506: Refactoring, testing and new features related to “users”&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Overview'''==&lt;br /&gt;
===Code refactoring===&lt;br /&gt;
''Refactoring'' is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior&amp;lt;ref&amp;gt;[http://refactoring.com/ Refactoring]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Refactoring adds to the value of any program that has at least one of the following shortcomings&amp;lt;ref&amp;gt;[http://jexp.de/papers/refactoring/refactoring/node9.html#SECTION00330000000000000000 Benefits of Code Refactoring] Michael Hunger. Oct. 25, 2000&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Programs that are hard to read are hard to modify;&lt;br /&gt;
* Programs that have duplicate logic are hard to modify;&lt;br /&gt;
* Programs that require additional behavior that requires you to change running code are hard to modify;&lt;br /&gt;
* Programs with complex conditional logic are hard to modify.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rspec===&lt;br /&gt;
RSpec is a [http://en.wikipedia.org/wiki/Behavior-driven_development behavior-driven development] (BDD) framework for the [http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby programming language], inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock. The framework can be considered a [http://en.wikipedia.org/wiki/Domain-specific_language domain-specific language] (DSL) and resembles a natural language specification&amp;lt;ref&amp;gt;[http://en.wikipedia.org/wiki/RSpec#cite_note-origin-4g Rspec]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Object-oriented Design Principles===&lt;br /&gt;
Object-oriented programming (OOP) is a programming language model organized around objects rather than &amp;quot;actions&amp;quot; and data rather than logic&amp;lt;ref&amp;gt;[http://searchsoa.techtarget.com/definition/object-oriented-programming Margaret Rouse. ''object-oriented programming (OOP) definition''. Aug 3, 2008]&amp;lt;/ref&amp;gt;. Historically, a program has been viewed as a logical procedure that takes input data, processes it, and produces output data. Though an Object oriented language provides us with highly useful and important programming concepts like '''Inheritance''', '''Polymorphism''', '''Abstraction''' and '''Encapsulation''' which definitely makes the code more efficient, it is equally important to have the knowledge of using them in the code. &lt;br /&gt;
''Object Oriented Design'' Principles are core of OOPS programming&amp;lt;ref&amp;gt;[http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-principles.html#ixzz3Ha8L3cfz Javin Paul. ''Blogspot''. March 3, 2012]&amp;lt;/ref&amp;gt;. It is important to know these design principles, to create clean and modular design. There are many design principles that help us to create clean and efficient code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=='''Project Resources'''==&lt;br /&gt;
* [https://github.com/CSC517-Proj2-E1506/expertiza GitHub Repository]&lt;br /&gt;
* [ VCL IP] (Log in as user2/password. Go to [ VCL analytic page])&lt;br /&gt;
* [https://github.com/expertiza/expertiza/pull/505 GitHub Pull Request Link] &lt;br /&gt;
* [https://travis-ci.org/expertiza/expertiza/builds/54516405 Travis CI build passed]&lt;br /&gt;
&lt;br /&gt;
=='''Todo List'''==&lt;br /&gt;
&amp;lt;b&amp;gt;Related files:&amp;lt;/b&amp;gt; &lt;br /&gt;
 * users_controller.rb&lt;br /&gt;
 * participants_controller.rb&lt;br /&gt;
 * user.rb&lt;br /&gt;
 * users/show.html.erb&lt;br /&gt;
*  Find the un-called methods if any and delete them. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*  Change the Rails 2 syntax to Rails 4 style.&lt;br /&gt;
*  Refactor users_controller.rb&lt;br /&gt;
** Change the white space for the second harf of this file, starts at “def edit”. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Separate the “paginate_list” method into two methods. The search method should be in model and the paginating method should be in the controller.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* New feature: delete users&lt;br /&gt;
** A user can be deleted if (s)he has not participated in an assignment. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user is participating in an assignment, the system will ask, “User is participating in k assignments.  Delete as a participant in these assignment(s)?”  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden.&lt;br /&gt;
*** rename (javascript calling update method in users_controller.rb) &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*** different users have different delete methods.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Write tests (with Rspec) for this feature.&amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* Testing feature: search for users&lt;br /&gt;
** In rails 4 branch, admins can search for the users with 1) users’ login names 2) users’ last or first names and 3) users’ emails. Please write tests (with Rspec) for this feature &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Delete Uncalled Methods'''==&lt;br /&gt;
&lt;br /&gt;
==='''Method'''===&lt;br /&gt;
&lt;br /&gt;
* The primary way we find unused method is right-click on each method's name, then choose &amp;quot;Find Usages&amp;quot;, as the following picture shows:&lt;br /&gt;
[[File:FindUsages.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Then the finding results will be displayed in the bottom, as the following picture shows:&lt;br /&gt;
[[File:FindResult.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
==='''Implementation'''===&lt;br /&gt;
&lt;br /&gt;
* In this way we identified the following method from '''''UserController.rb''''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def self.participants_in(assignment_id)&lt;br /&gt;
 users = Array.new&lt;br /&gt;
 participants = AssignmentParticipant.find_by_parent_id(assignment_id)&lt;br /&gt;
 participants.each{&lt;br /&gt;
   |participant|&lt;br /&gt;
   users &amp;lt;&amp;lt; User.find(participant.user_id)&lt;br /&gt;
 }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* And the following methods from '''''User.rb'''''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def assign_random_password&lt;br /&gt;
 if self.password.blank?&lt;br /&gt;
   self.password = self.random_password&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def self.random_password(size=8)&lt;br /&gt;
 random_pronouncable_password((size/2).round) + rand.to_s[2,3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def get_author_name&lt;br /&gt;
 return self.fullname&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* There's one method '''''salt_first''''' in '''''User.rb''''' cannot be deleted. Salt is a small chunk of random data to the password before it's hashed. The salt is then stored along with the hash in the database, and used to check potentially valid passwords&amp;lt;ref&amp;gt;[https://github.com/codahale/bcrypt-ruby Salt]&amp;lt;/ref&amp;gt;. Here's the function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def salt_first?&lt;br /&gt;
    true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Change Rails 2 syntax to Rails 4'''==&lt;br /&gt;
* One main problem(bug) in Expertiza is that you can create one new user from the UI, but the second time you try to create one, you get “undefined ‘with_scope’” (see [https://github.com/expertiza/expertiza/issues/504 Issue 504 in Github]), as the following picture shows:&lt;br /&gt;
&lt;br /&gt;
[[File:WithScopeError.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
* When calling '''''@user.save''''' method, it will implicitly call the '''''ActiveRecord::Base#with_scope''''' method. However, this method is no longer supported in current Rails 4.1.5 version, which is used by Expertiza. We had searched a lot through the Internet, but find very limited useful information on this topic. It doesn't seem reasonable for '''''@user.save''''' still calling the '''''with_scope''''' method, since all versions if Rails, as well as ActiveRecord, are marked as the latest in '''''Gemfile.lock'''''.&lt;br /&gt;
&lt;br /&gt;
=='''Refactor users_controller.rb'''==&lt;br /&gt;
===='''Refactor the “paginate_list” method'''====&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;paginate_list&amp;quot; method is a function in &amp;quot;users_controller.rb&amp;quot;. It will be called if you do search in Manage-&amp;gt;Users page. It has two components: search for users, paginate the results.&lt;br /&gt;
&lt;br /&gt;
However, the controller should not know how the information is retrieved. So we would like to refactor this method by seperating it into search method and paginating method. The search method is in model and the paginating method is still in controller.&lt;br /&gt;
&lt;br /&gt;
The code below is the &amp;quot;paginate_list&amp;quot; method in official Expertiza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# For filtering the users list with proper search and pagination.&lt;br /&gt;
def paginate_list(role, user_id, letter)&lt;br /&gt;
  paginate_options = {&amp;quot;1&amp;quot; =&amp;gt; 25, &amp;quot;2&amp;quot; =&amp;gt; 50, &amp;quot;3&amp;quot; =&amp;gt; 100}&lt;br /&gt;
&lt;br /&gt;
  # If the above hash does not have a value for the key,&lt;br /&gt;
  # it means that we need to show all the users on the page&lt;br /&gt;
  #&lt;br /&gt;
  # Just a point to remember, when we use pagination, the&lt;br /&gt;
  # 'users' variable should be an object, not an array&lt;br /&gt;
&lt;br /&gt;
  #The type of condition for the search depends on what the user has selected from the search_by dropdown&lt;br /&gt;
  condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot; #default used when clicking on letters&lt;br /&gt;
  search_filter = letter + '%'&lt;br /&gt;
  @search_by = params[:search_by]&lt;br /&gt;
  if @search_by == '1'  #search by user name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '2' # search by full name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and fullname like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '3' # search by email&lt;br /&gt;
     condition = &amp;quot;(role_id in (?) or id = ?) and email like ?&amp;quot;&lt;br /&gt;
     search_filter = '%' + letter + '%'&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  if (paginate_options[&amp;quot;#{@per_page}&amp;quot;].nil?) #displaying all - no pagination&lt;br /&gt;
    users = User.order('name').where( [condition, role.get_available_roles, user_id, search_filter]).paginate(:page =&amp;gt; params[:page], :per_page =&amp;gt; User.count)&lt;br /&gt;
  else #some pagination is active - use the per_page&lt;br /&gt;
    users = User.page(params[:page]).order('name').per_page(paginate_options[&amp;quot;#{@per_page}&amp;quot;]).where([condition, role.get_available_roles, user_id, search_filter])&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the code we can see that the search method needs four parameters:&lt;br /&gt;
* role: user can only search users below his role&lt;br /&gt;
* user_id: current user id&lt;br /&gt;
* letter: keyword in search&lt;br /&gt;
* search_by: search by user name, full name or email&lt;br /&gt;
&lt;br /&gt;
Base on this, we implemented the search method in &amp;quot;user.rb&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def self.search_users(role, user_id, letter, search_by)&lt;br /&gt;
  if search_by == '1'  #search by user name&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  elsif search_by == '2' # search by full name&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and fullname like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  elsif search_by == '3' # search by email&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and email like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  else #default used when clicking on letters&lt;br /&gt;
    search_filter = letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the original &amp;quot;paginate_list&amp;quot; method is modified as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# For filtering the users list with proper search and pagination.&lt;br /&gt;
def paginate_list(role, user_id, letter)&lt;br /&gt;
  paginate_options = {&amp;quot;1&amp;quot; =&amp;gt; 25, &amp;quot;2&amp;quot; =&amp;gt; 50, &amp;quot;3&amp;quot; =&amp;gt; 100}&lt;br /&gt;
&lt;br /&gt;
  # If the above hash does not have a value for the key,&lt;br /&gt;
  # it means that we need to show all the users on the page&lt;br /&gt;
  #&lt;br /&gt;
  # Just a point to remember, when we use pagination, the&lt;br /&gt;
  # 'users' variable should be an object, not an array&lt;br /&gt;
&lt;br /&gt;
  #The type of condition for the search depends on what the user has selected from the search_by dropdown&lt;br /&gt;
  @search_by = params[:search_by]&lt;br /&gt;
&lt;br /&gt;
  # search for corresponding users&lt;br /&gt;
  users = User.search_users(role, user_id, letter, @search_by)&lt;br /&gt;
&lt;br /&gt;
  # paginate&lt;br /&gt;
  if (paginate_options[&amp;quot;#{@per_page}&amp;quot;].nil?) #displaying all - no pagination&lt;br /&gt;
    users = users.paginate(:page =&amp;gt; params[:page], :per_page =&amp;gt; User.count)&lt;br /&gt;
  else #some pagination is active - use the per_page&lt;br /&gt;
    users = users.page(params[:page]).per_page(paginate_options[&amp;quot;#{@per_page}&amp;quot;])&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''New feature: delete users'''==&lt;br /&gt;
&lt;br /&gt;
===='''Design'''====&lt;br /&gt;
&lt;br /&gt;
At the very beginning, we decide to use &amp;quot;Cascading Delete&amp;quot; to delete users. Because there are many relationship between different users. They can be reviewer, reviewee, teaching assistant, and so on.If we have to delete an user, we have to not only delete the record in ''user'' table, but also other related tables.&lt;br /&gt;
&lt;br /&gt;
So, we divide all users into two set, one is '''new users''' without any relationship, the other is the '''old user''' with some relationships. And we find that it is quite easy to achieve the functionality of deleting new users. When deleting old users, we find some problems. Because old users may be a reviewer before and score some assignments. If we delete some old users, the assignments' review scores will be a mess.&lt;br /&gt;
&lt;br /&gt;
After discussing with professor, we decide to deprecate&amp;quot;Cascading Delete&amp;quot;. And we use below algorithm to handle user deletion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS0.png‎  |frame|center|Confirm box flow diagram]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* A user can be deleted if (s)he has not participated in an assignment;&lt;br /&gt;
* If the user is participating in an assignment, the system will ask, “User is participating in k assignments. Delete as a participant in these assignment(s)?”;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS1.png‎  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS2.png‎  |frame|center|Rename confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Rename (javascript calling update method in users_controller.rb);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS3.png‎  |frame|center|Rename success 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS4.png‎  |frame|center|Cannot delete]]&lt;br /&gt;
&lt;br /&gt;
===='''Implementation'''====&lt;br /&gt;
&lt;br /&gt;
We add a '''userDeleteConfirmBox.js''' file to implement this unique confirm box algorithm.&lt;br /&gt;
&lt;br /&gt;
* First, we overwrite the Rails default confirm function.&lt;br /&gt;
 $.rails.allowAction = function(link) {&lt;br /&gt;
   console.log(link.attr('data-relationship'))&lt;br /&gt;
   console.log(link.attr('data-username'))&lt;br /&gt;
   if ((!link.attr('data-confirm')) || (link.attr('data-relationship') &amp;amp;&amp;amp; link.attr('data-relationship') == 'false')) {&lt;br /&gt;
    return true;&lt;br /&gt;
   }&lt;br /&gt;
   $.rails.showConfirmDialog(link);&lt;br /&gt;
   return false;&lt;br /&gt;
 };&lt;br /&gt;
 $.rails.confirmed = function(link) {&lt;br /&gt;
   link.removeAttr('data-confirm');&lt;br /&gt;
   return link.trigger('click.rails');&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* Then, we write code to achieve customed confirm box using our own algorithm.&lt;br /&gt;
 $.rails.showConfirmDialog = function(link) {&lt;br /&gt;
  var message = link.attr('data-confirm');&lt;br /&gt;
  //confirmation box style&lt;br /&gt;
  $(function() {&lt;br /&gt;
    $(html1).modal();&lt;br /&gt;
    $(&amp;quot;#dialog-confirm1&amp;quot;).dialog({&lt;br /&gt;
      width: 340,&lt;br /&gt;
      buttons: {&lt;br /&gt;
        &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          location.reload();&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;Yes&amp;quot;: function() {&lt;br /&gt;
          //return $.rails.confirmed(link);&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          $(html2).modal();&lt;br /&gt;
          $(&amp;quot;#dialog-confirm2&amp;quot;).dialog({&lt;br /&gt;
            width: 340,&lt;br /&gt;
            buttons: {&lt;br /&gt;
              &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
                $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;Yes&amp;quot;: function() {                 &lt;br /&gt;
                    $('#rename').click() &lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html3).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm3&amp;quot;).dialog({&lt;br /&gt;
                    width: 340,&lt;br /&gt;
                  });&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;No, delete any way!&amp;quot;: function() {&lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html4).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm4&amp;quot;).dialog({&lt;br /&gt;
                      width: 340,&lt;br /&gt;
                      buttons: {&lt;br /&gt;
                        &amp;quot;Close&amp;quot;: function() {&lt;br /&gt;
                          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                          location.reload();&lt;br /&gt;
                        }&lt;br /&gt;
                      }&lt;br /&gt;
                  });&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
           });&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     });&lt;br /&gt;
  });&lt;br /&gt;
  return $('#dialog-confirm .confirm').on('click', function() {&lt;br /&gt;
    return $.rails.confirmed(link);&lt;br /&gt;
  });&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* After that, we all the if condition in '''/users/show.html.erb''' file. So when deleting the old users, Expertiza uses the functionality and customed confirm box we define; when deleting the new users, Expertiza will use the default confirm box.&lt;br /&gt;
  &amp;lt;% if @assignment_participant_num != 0 and (!@maps.nil? or @maps.length != 0)%&amp;gt; &lt;br /&gt;
      &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User is participating in #{@assignment_participant_num} assignments.&amp;lt;br/&amp;gt;Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'true', :username =&amp;gt; @user.name}, :method =&amp;gt; :delete, remote: true%&amp;gt;   &lt;br /&gt;
  &amp;lt;% else %&amp;gt;&lt;br /&gt;
       &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User joins in #{@assignment_participant_num} assignment(s), but without participates in&lt;br /&gt;
 any assignments. Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'false'}, :method =&amp;gt; :delete, remote: true%&amp;gt;&lt;br /&gt;
   &amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Testing feature: search for users'''==&lt;br /&gt;
&lt;br /&gt;
==='''Design'''===&lt;br /&gt;
&lt;br /&gt;
We write some features test to test &amp;quot;search for users&amp;quot; functionality.&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users bylogin names&lt;br /&gt;
 feature 'Method 1: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by login name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'student'&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Student, Perfect&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;pstudent@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by first name or last name&lt;br /&gt;
 feature 'Method2: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by last or first name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'Bob'&lt;br /&gt;
    find('#search_by').select 'Full name'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by email&lt;br /&gt;
 feature 'Method3: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by email' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'bdole@dev.null'&lt;br /&gt;
    find('#search_by').select 'Email'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor deletes new users&lt;br /&gt;
 feature 'Instructor delete a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'which has no relationship' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    #in order to show whole user list&lt;br /&gt;
    fill_in 'letter', with: ''&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    click_link 'student'&lt;br /&gt;
    click_link 'Delete'&lt;br /&gt;
    expect(page).to_not have_content(&amp;quot;student&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;instructor&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==='''Implementation'''===&lt;br /&gt;
 rspec spec/features/users_spec.rb&lt;br /&gt;
&lt;br /&gt;
[[File:Rspec1.png‎  |frame|center|Rspec feature test pass]]&lt;br /&gt;
&lt;br /&gt;
=='''References'''==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95398</id>
		<title>CSC/ECE 517 Spring 2015/oss E1506 SYZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95398"/>
		<updated>2015-03-22T15:35:05Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Change Rails 2 syntax to Rails 4 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;E1506: Refactoring, testing and new features related to “users”&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Overview'''==&lt;br /&gt;
===Code refactoring===&lt;br /&gt;
''Refactoring'' is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior&amp;lt;ref&amp;gt;[http://refactoring.com/ Refactoring]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Refactoring adds to the value of any program that has at least one of the following shortcomings&amp;lt;ref&amp;gt;[http://jexp.de/papers/refactoring/refactoring/node9.html#SECTION00330000000000000000 Benefits of Code Refactoring] Michael Hunger. Oct. 25, 2000&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Programs that are hard to read are hard to modify;&lt;br /&gt;
* Programs that have duplicate logic are hard to modify;&lt;br /&gt;
* Programs that require additional behavior that requires you to change running code are hard to modify;&lt;br /&gt;
* Programs with complex conditional logic are hard to modify.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rspec===&lt;br /&gt;
RSpec is a [http://en.wikipedia.org/wiki/Behavior-driven_development behavior-driven development] (BDD) framework for the [http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby programming language], inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock. The framework can be considered a [http://en.wikipedia.org/wiki/Domain-specific_language domain-specific language] (DSL) and resembles a natural language specification&amp;lt;ref&amp;gt;[http://en.wikipedia.org/wiki/RSpec#cite_note-origin-4g Rspec]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Object-oriented Design Principles===&lt;br /&gt;
Object-oriented programming (OOP) is a programming language model organized around objects rather than &amp;quot;actions&amp;quot; and data rather than logic&amp;lt;ref&amp;gt;[http://searchsoa.techtarget.com/definition/object-oriented-programming Margaret Rouse. ''object-oriented programming (OOP) definition''. Aug 3, 2008]&amp;lt;/ref&amp;gt;. Historically, a program has been viewed as a logical procedure that takes input data, processes it, and produces output data. Though an Object oriented language provides us with highly useful and important programming concepts like '''Inheritance''', '''Polymorphism''', '''Abstraction''' and '''Encapsulation''' which definitely makes the code more efficient, it is equally important to have the knowledge of using them in the code. &lt;br /&gt;
''Object Oriented Design'' Principles are core of OOPS programming&amp;lt;ref&amp;gt;[http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-principles.html#ixzz3Ha8L3cfz Javin Paul. ''Blogspot''. March 3, 2012]&amp;lt;/ref&amp;gt;. It is important to know these design principles, to create clean and modular design. There are many design principles that help us to create clean and efficient code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=='''Project Resources'''==&lt;br /&gt;
* [https://github.com/CSC517-Proj2-E1506/expertiza GitHub Repository]&lt;br /&gt;
* [ VCL IP] (Log in as user2/password. Go to [ VCL analytic page])&lt;br /&gt;
* [https://github.com/expertiza/expertiza/pull/505 GitHub Pull Request Link] &lt;br /&gt;
* [https://travis-ci.org/expertiza/expertiza/builds/54516405 Travis CI build passed]&lt;br /&gt;
&lt;br /&gt;
=='''Todo List'''==&lt;br /&gt;
&amp;lt;b&amp;gt;Related files:&amp;lt;/b&amp;gt; &lt;br /&gt;
 * users_controller.rb&lt;br /&gt;
 * participants_controller.rb&lt;br /&gt;
 * user.rb&lt;br /&gt;
 * users/show.html.erb&lt;br /&gt;
*  Find the un-called methods if any and delete them. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*  Change the Rails 2 syntax to Rails 4 style.&lt;br /&gt;
*  Refactor users_controller.rb&lt;br /&gt;
** Change the white space for the second harf of this file, starts at “def edit”. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Separate the “paginate_list” method into two methods. The search method should be in model and the paginating method should be in the controller.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* New feature: delete users&lt;br /&gt;
** A user can be deleted if (s)he has not participated in an assignment. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user is participating in an assignment, the system will ask, “User is participating in k assignments.  Delete as a participant in these assignment(s)?”  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden.&lt;br /&gt;
*** rename (javascript calling update method in users_controller.rb) &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*** different users have different delete methods.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Write tests (with Rspec) for this feature.&amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* Testing feature: search for users&lt;br /&gt;
** In rails 4 branch, admins can search for the users with 1) users’ login names 2) users’ last or first names and 3) users’ emails. Please write tests (with Rspec) for this feature &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Delete Uncalled Methods'''==&lt;br /&gt;
&lt;br /&gt;
==='''Method'''===&lt;br /&gt;
&lt;br /&gt;
* The primary way we find unused method is right-click on each method's name, then choose &amp;quot;Find Usages&amp;quot;, as the following picture shows:&lt;br /&gt;
[[File:FindUsages.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Then the finding results will be displayed in the bottom, as the following picture shows:&lt;br /&gt;
[[File:FindResult.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
==='''Implementation'''===&lt;br /&gt;
&lt;br /&gt;
* In this way we identified the following method from '''''UserController.rb''''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def self.participants_in(assignment_id)&lt;br /&gt;
 users = Array.new&lt;br /&gt;
 participants = AssignmentParticipant.find_by_parent_id(assignment_id)&lt;br /&gt;
 participants.each{&lt;br /&gt;
   |participant|&lt;br /&gt;
   users &amp;lt;&amp;lt; User.find(participant.user_id)&lt;br /&gt;
 }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* And the following methods from '''''User.rb'''''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def assign_random_password&lt;br /&gt;
 if self.password.blank?&lt;br /&gt;
   self.password = self.random_password&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def self.random_password(size=8)&lt;br /&gt;
 random_pronouncable_password((size/2).round) + rand.to_s[2,3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def get_author_name&lt;br /&gt;
 return self.fullname&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* There's one method '''''salt_first''''' in '''''User.rb''''' cannot be deleted. Salt is a small chunk of random data to the password before it's hashed. The salt is then stored along with the hash in the database, and used to check potentially valid passwords&amp;lt;ref&amp;gt;[https://github.com/codahale/bcrypt-ruby Salt]&amp;lt;/ref&amp;gt;. Here's the function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def salt_first?&lt;br /&gt;
    true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Change Rails 2 syntax to Rails 4'''==&lt;br /&gt;
* One main problem(bug) in Expertiza is that you can create one new user from the UI, but the second time you try to create one, you get “undefined ‘with_scope’” (see [https://github.com/expertiza/expertiza/issues/504 Issue 504 in Github]), as the following picture shows:&lt;br /&gt;
&lt;br /&gt;
[[File:WithScopeError.PNG  |frame|center|Delete confirm box]]]&lt;br /&gt;
&lt;br /&gt;
* When calling '''''@user.save''''' method, it will implicitly call the '''''ActiveRecord::Base#with_scope''''' method. However, this method is no longer supported in current Rails 4.1.5 version, which is used by Expertiza. We had searched a lot through the Internet, but find very limited useful information on this topic. It doesn't seem reasonable for '''''@user.save''''' still calling the '''''with_scope''''' method, since all versions if Rails, as well as ActiveRecord, are marked as the latest in '''''Gemfile.lock'''''.&lt;br /&gt;
&lt;br /&gt;
=='''Refactor users_controller.rb'''==&lt;br /&gt;
===='''Refactor the “paginate_list” method'''====&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;paginate_list&amp;quot; method is a function in &amp;quot;users_controller.rb&amp;quot;. It will be called if you do search in Manage-&amp;gt;Users page. It has two components: search for users, paginate the results.&lt;br /&gt;
&lt;br /&gt;
However, the controller should not know how the information is retrieved. So we would like to refactor this method by seperating it into search method and paginating method. The search method is in model and the paginating method is still in controller.&lt;br /&gt;
&lt;br /&gt;
The code below is the &amp;quot;paginate_list&amp;quot; method in official Expertiza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# For filtering the users list with proper search and pagination.&lt;br /&gt;
def paginate_list(role, user_id, letter)&lt;br /&gt;
  paginate_options = {&amp;quot;1&amp;quot; =&amp;gt; 25, &amp;quot;2&amp;quot; =&amp;gt; 50, &amp;quot;3&amp;quot; =&amp;gt; 100}&lt;br /&gt;
&lt;br /&gt;
  # If the above hash does not have a value for the key,&lt;br /&gt;
  # it means that we need to show all the users on the page&lt;br /&gt;
  #&lt;br /&gt;
  # Just a point to remember, when we use pagination, the&lt;br /&gt;
  # 'users' variable should be an object, not an array&lt;br /&gt;
&lt;br /&gt;
  #The type of condition for the search depends on what the user has selected from the search_by dropdown&lt;br /&gt;
  condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot; #default used when clicking on letters&lt;br /&gt;
  search_filter = letter + '%'&lt;br /&gt;
  @search_by = params[:search_by]&lt;br /&gt;
  if @search_by == '1'  #search by user name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '2' # search by full name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and fullname like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '3' # search by email&lt;br /&gt;
     condition = &amp;quot;(role_id in (?) or id = ?) and email like ?&amp;quot;&lt;br /&gt;
     search_filter = '%' + letter + '%'&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  if (paginate_options[&amp;quot;#{@per_page}&amp;quot;].nil?) #displaying all - no pagination&lt;br /&gt;
    users = User.order('name').where( [condition, role.get_available_roles, user_id, search_filter]).paginate(:page =&amp;gt; params[:page], :per_page =&amp;gt; User.count)&lt;br /&gt;
  else #some pagination is active - use the per_page&lt;br /&gt;
    users = User.page(params[:page]).order('name').per_page(paginate_options[&amp;quot;#{@per_page}&amp;quot;]).where([condition, role.get_available_roles, user_id, search_filter])&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the code we can see that the search method needs four parameters:&lt;br /&gt;
* role: user can only search users below his role&lt;br /&gt;
* user_id: current user id&lt;br /&gt;
* letter: keyword in search&lt;br /&gt;
* search_by: search by user name, full name or email&lt;br /&gt;
&lt;br /&gt;
Base on this, we implemented the search method in &amp;quot;user.rb&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def self.search_users(role, user_id, letter, search_by)&lt;br /&gt;
  if search_by == '1'  #search by user name&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  elsif search_by == '2' # search by full name&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and fullname like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  elsif search_by == '3' # search by email&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and email like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  else #default used when clicking on letters&lt;br /&gt;
    search_filter = letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the original &amp;quot;paginate_list&amp;quot; method is modified as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# For filtering the users list with proper search and pagination.&lt;br /&gt;
def paginate_list(role, user_id, letter)&lt;br /&gt;
  paginate_options = {&amp;quot;1&amp;quot; =&amp;gt; 25, &amp;quot;2&amp;quot; =&amp;gt; 50, &amp;quot;3&amp;quot; =&amp;gt; 100}&lt;br /&gt;
&lt;br /&gt;
  # If the above hash does not have a value for the key,&lt;br /&gt;
  # it means that we need to show all the users on the page&lt;br /&gt;
  #&lt;br /&gt;
  # Just a point to remember, when we use pagination, the&lt;br /&gt;
  # 'users' variable should be an object, not an array&lt;br /&gt;
&lt;br /&gt;
  #The type of condition for the search depends on what the user has selected from the search_by dropdown&lt;br /&gt;
  @search_by = params[:search_by]&lt;br /&gt;
&lt;br /&gt;
  # search for corresponding users&lt;br /&gt;
  users = User.search_users(role, user_id, letter, @search_by)&lt;br /&gt;
&lt;br /&gt;
  # paginate&lt;br /&gt;
  if (paginate_options[&amp;quot;#{@per_page}&amp;quot;].nil?) #displaying all - no pagination&lt;br /&gt;
    users = users.paginate(:page =&amp;gt; params[:page], :per_page =&amp;gt; User.count)&lt;br /&gt;
  else #some pagination is active - use the per_page&lt;br /&gt;
    users = users.page(params[:page]).per_page(paginate_options[&amp;quot;#{@per_page}&amp;quot;])&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''New feature: delete users'''==&lt;br /&gt;
&lt;br /&gt;
===='''Design'''====&lt;br /&gt;
&lt;br /&gt;
At the very beginning, we decide to use &amp;quot;Cascading Delete&amp;quot; to delete users. Because there are many relationship between different users. They can be reviewer, reviewee, teaching assistant, and so on.If we have to delete an user, we have to not only delete the record in ''user'' table, but also other related tables.&lt;br /&gt;
&lt;br /&gt;
So, we divide all users into two set, one is '''new users''' without any relationship, the other is the '''old user''' with some relationships. And we find that it is quite easy to achieve the functionality of deleting new users. When deleting old users, we find some problems. Because old users may be a reviewer before and score some assignments. If we delete some old users, the assignments' review scores will be a mess.&lt;br /&gt;
&lt;br /&gt;
After discussing with professor, we decide to deprecate&amp;quot;Cascading Delete&amp;quot;. And we use below algorithm to handle user deletion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS0.png‎  |frame|center|Confirm box flow diagram]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* A user can be deleted if (s)he has not participated in an assignment;&lt;br /&gt;
* If the user is participating in an assignment, the system will ask, “User is participating in k assignments. Delete as a participant in these assignment(s)?”;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS1.png‎  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS2.png‎  |frame|center|Rename confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Rename (javascript calling update method in users_controller.rb);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS3.png‎  |frame|center|Rename success 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS4.png‎  |frame|center|Cannot delete]]&lt;br /&gt;
&lt;br /&gt;
===='''Implementation'''====&lt;br /&gt;
&lt;br /&gt;
We add a '''userDeleteConfirmBox.js''' file to implement this unique confirm box algorithm.&lt;br /&gt;
&lt;br /&gt;
* First, we overwrite the Rails default confirm function.&lt;br /&gt;
 $.rails.allowAction = function(link) {&lt;br /&gt;
   console.log(link.attr('data-relationship'))&lt;br /&gt;
   console.log(link.attr('data-username'))&lt;br /&gt;
   if ((!link.attr('data-confirm')) || (link.attr('data-relationship') &amp;amp;&amp;amp; link.attr('data-relationship') == 'false')) {&lt;br /&gt;
    return true;&lt;br /&gt;
   }&lt;br /&gt;
   $.rails.showConfirmDialog(link);&lt;br /&gt;
   return false;&lt;br /&gt;
 };&lt;br /&gt;
 $.rails.confirmed = function(link) {&lt;br /&gt;
   link.removeAttr('data-confirm');&lt;br /&gt;
   return link.trigger('click.rails');&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* Then, we write code to achieve customed confirm box using our own algorithm.&lt;br /&gt;
 $.rails.showConfirmDialog = function(link) {&lt;br /&gt;
  var message = link.attr('data-confirm');&lt;br /&gt;
  //confirmation box style&lt;br /&gt;
  $(function() {&lt;br /&gt;
    $(html1).modal();&lt;br /&gt;
    $(&amp;quot;#dialog-confirm1&amp;quot;).dialog({&lt;br /&gt;
      width: 340,&lt;br /&gt;
      buttons: {&lt;br /&gt;
        &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          location.reload();&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;Yes&amp;quot;: function() {&lt;br /&gt;
          //return $.rails.confirmed(link);&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          $(html2).modal();&lt;br /&gt;
          $(&amp;quot;#dialog-confirm2&amp;quot;).dialog({&lt;br /&gt;
            width: 340,&lt;br /&gt;
            buttons: {&lt;br /&gt;
              &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
                $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;Yes&amp;quot;: function() {                 &lt;br /&gt;
                    $('#rename').click() &lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html3).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm3&amp;quot;).dialog({&lt;br /&gt;
                    width: 340,&lt;br /&gt;
                  });&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;No, delete any way!&amp;quot;: function() {&lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html4).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm4&amp;quot;).dialog({&lt;br /&gt;
                      width: 340,&lt;br /&gt;
                      buttons: {&lt;br /&gt;
                        &amp;quot;Close&amp;quot;: function() {&lt;br /&gt;
                          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                          location.reload();&lt;br /&gt;
                        }&lt;br /&gt;
                      }&lt;br /&gt;
                  });&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
           });&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     });&lt;br /&gt;
  });&lt;br /&gt;
  return $('#dialog-confirm .confirm').on('click', function() {&lt;br /&gt;
    return $.rails.confirmed(link);&lt;br /&gt;
  });&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* After that, we all the if condition in '''/users/show.html.erb''' file. So when deleting the old users, Expertiza uses the functionality and customed confirm box we define; when deleting the new users, Expertiza will use the default confirm box.&lt;br /&gt;
  &amp;lt;% if @assignment_participant_num != 0 and (!@maps.nil? or @maps.length != 0)%&amp;gt; &lt;br /&gt;
      &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User is participating in #{@assignment_participant_num} assignments.&amp;lt;br/&amp;gt;Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'true', :username =&amp;gt; @user.name}, :method =&amp;gt; :delete, remote: true%&amp;gt;   &lt;br /&gt;
  &amp;lt;% else %&amp;gt;&lt;br /&gt;
       &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User joins in #{@assignment_participant_num} assignment(s), but without participates in&lt;br /&gt;
 any assignments. Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'false'}, :method =&amp;gt; :delete, remote: true%&amp;gt;&lt;br /&gt;
   &amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Testing feature: search for users'''==&lt;br /&gt;
&lt;br /&gt;
==='''Design'''===&lt;br /&gt;
&lt;br /&gt;
We write some features test to test &amp;quot;search for users&amp;quot; functionality.&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users bylogin names&lt;br /&gt;
 feature 'Method 1: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by login name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'student'&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Student, Perfect&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;pstudent@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by first name or last name&lt;br /&gt;
 feature 'Method2: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by last or first name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'Bob'&lt;br /&gt;
    find('#search_by').select 'Full name'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by email&lt;br /&gt;
 feature 'Method3: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by email' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'bdole@dev.null'&lt;br /&gt;
    find('#search_by').select 'Email'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor deletes new users&lt;br /&gt;
 feature 'Instructor delete a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'which has no relationship' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    #in order to show whole user list&lt;br /&gt;
    fill_in 'letter', with: ''&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    click_link 'student'&lt;br /&gt;
    click_link 'Delete'&lt;br /&gt;
    expect(page).to_not have_content(&amp;quot;student&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;instructor&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==='''Implementation'''===&lt;br /&gt;
 rspec spec/features/users_spec.rb&lt;br /&gt;
&lt;br /&gt;
[[File:Rspec1.png‎  |frame|center|Rspec feature test pass]]&lt;br /&gt;
&lt;br /&gt;
=='''References'''==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:WithScopeError.PNG&amp;diff=95397</id>
		<title>File:WithScopeError.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:WithScopeError.PNG&amp;diff=95397"/>
		<updated>2015-03-22T15:34:02Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95396</id>
		<title>CSC/ECE 517 Spring 2015/oss E1506 SYZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95396"/>
		<updated>2015-03-22T15:33:09Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Change Rails 2 syntax to Rails 4 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;E1506: Refactoring, testing and new features related to “users”&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Overview'''==&lt;br /&gt;
===Code refactoring===&lt;br /&gt;
''Refactoring'' is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior&amp;lt;ref&amp;gt;[http://refactoring.com/ Refactoring]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Refactoring adds to the value of any program that has at least one of the following shortcomings&amp;lt;ref&amp;gt;[http://jexp.de/papers/refactoring/refactoring/node9.html#SECTION00330000000000000000 Benefits of Code Refactoring] Michael Hunger. Oct. 25, 2000&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Programs that are hard to read are hard to modify;&lt;br /&gt;
* Programs that have duplicate logic are hard to modify;&lt;br /&gt;
* Programs that require additional behavior that requires you to change running code are hard to modify;&lt;br /&gt;
* Programs with complex conditional logic are hard to modify.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rspec===&lt;br /&gt;
RSpec is a [http://en.wikipedia.org/wiki/Behavior-driven_development behavior-driven development] (BDD) framework for the [http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby programming language], inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock. The framework can be considered a [http://en.wikipedia.org/wiki/Domain-specific_language domain-specific language] (DSL) and resembles a natural language specification&amp;lt;ref&amp;gt;[http://en.wikipedia.org/wiki/RSpec#cite_note-origin-4g Rspec]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Object-oriented Design Principles===&lt;br /&gt;
Object-oriented programming (OOP) is a programming language model organized around objects rather than &amp;quot;actions&amp;quot; and data rather than logic&amp;lt;ref&amp;gt;[http://searchsoa.techtarget.com/definition/object-oriented-programming Margaret Rouse. ''object-oriented programming (OOP) definition''. Aug 3, 2008]&amp;lt;/ref&amp;gt;. Historically, a program has been viewed as a logical procedure that takes input data, processes it, and produces output data. Though an Object oriented language provides us with highly useful and important programming concepts like '''Inheritance''', '''Polymorphism''', '''Abstraction''' and '''Encapsulation''' which definitely makes the code more efficient, it is equally important to have the knowledge of using them in the code. &lt;br /&gt;
''Object Oriented Design'' Principles are core of OOPS programming&amp;lt;ref&amp;gt;[http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-principles.html#ixzz3Ha8L3cfz Javin Paul. ''Blogspot''. March 3, 2012]&amp;lt;/ref&amp;gt;. It is important to know these design principles, to create clean and modular design. There are many design principles that help us to create clean and efficient code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=='''Project Resources'''==&lt;br /&gt;
* [https://github.com/CSC517-Proj2-E1506/expertiza GitHub Repository]&lt;br /&gt;
* [ VCL IP] (Log in as user2/password. Go to [ VCL analytic page])&lt;br /&gt;
* [https://github.com/expertiza/expertiza/pull/505 GitHub Pull Request Link] &lt;br /&gt;
* [https://travis-ci.org/expertiza/expertiza/builds/54516405 Travis CI build passed]&lt;br /&gt;
&lt;br /&gt;
=='''Todo List'''==&lt;br /&gt;
&amp;lt;b&amp;gt;Related files:&amp;lt;/b&amp;gt; &lt;br /&gt;
 * users_controller.rb&lt;br /&gt;
 * participants_controller.rb&lt;br /&gt;
 * user.rb&lt;br /&gt;
 * users/show.html.erb&lt;br /&gt;
*  Find the un-called methods if any and delete them. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*  Change the Rails 2 syntax to Rails 4 style.&lt;br /&gt;
*  Refactor users_controller.rb&lt;br /&gt;
** Change the white space for the second harf of this file, starts at “def edit”. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Separate the “paginate_list” method into two methods. The search method should be in model and the paginating method should be in the controller.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* New feature: delete users&lt;br /&gt;
** A user can be deleted if (s)he has not participated in an assignment. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user is participating in an assignment, the system will ask, “User is participating in k assignments.  Delete as a participant in these assignment(s)?”  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden.&lt;br /&gt;
*** rename (javascript calling update method in users_controller.rb) &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*** different users have different delete methods.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Write tests (with Rspec) for this feature.&amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* Testing feature: search for users&lt;br /&gt;
** In rails 4 branch, admins can search for the users with 1) users’ login names 2) users’ last or first names and 3) users’ emails. Please write tests (with Rspec) for this feature &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Delete Uncalled Methods'''==&lt;br /&gt;
&lt;br /&gt;
==='''Method'''===&lt;br /&gt;
&lt;br /&gt;
* The primary way we find unused method is right-click on each method's name, then choose &amp;quot;Find Usages&amp;quot;, as the following picture shows:&lt;br /&gt;
[[File:FindUsages.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Then the finding results will be displayed in the bottom, as the following picture shows:&lt;br /&gt;
[[File:FindResult.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
==='''Implementation'''===&lt;br /&gt;
&lt;br /&gt;
* In this way we identified the following method from '''''UserController.rb''''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def self.participants_in(assignment_id)&lt;br /&gt;
 users = Array.new&lt;br /&gt;
 participants = AssignmentParticipant.find_by_parent_id(assignment_id)&lt;br /&gt;
 participants.each{&lt;br /&gt;
   |participant|&lt;br /&gt;
   users &amp;lt;&amp;lt; User.find(participant.user_id)&lt;br /&gt;
 }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* And the following methods from '''''User.rb'''''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def assign_random_password&lt;br /&gt;
 if self.password.blank?&lt;br /&gt;
   self.password = self.random_password&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def self.random_password(size=8)&lt;br /&gt;
 random_pronouncable_password((size/2).round) + rand.to_s[2,3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def get_author_name&lt;br /&gt;
 return self.fullname&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* There's one method '''''salt_first''''' in '''''User.rb''''' cannot be deleted. Salt is a small chunk of random data to the password before it's hashed. The salt is then stored along with the hash in the database, and used to check potentially valid passwords&amp;lt;ref&amp;gt;[https://github.com/codahale/bcrypt-ruby Salt]&amp;lt;/ref&amp;gt;. Here's the function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def salt_first?&lt;br /&gt;
    true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Change Rails 2 syntax to Rails 4'''==&lt;br /&gt;
* One main problem(bug) in Expertiza is that you can create one new user from the UI, but the second time you try to create one, you get “undefined ‘with_scope’” (see [https://github.com/expertiza/expertiza/issues/504 Issue 504 in Github]), as the following picture shows:&lt;br /&gt;
&lt;br /&gt;
[[File:WithScopeError.PNG]]&lt;br /&gt;
&lt;br /&gt;
* When calling '''''@user.save''''' method, it will implicitly call the '''''ActiveRecord::Base#with_scope''''' method. However, this method is no longer supported in current Rails 4.1.5 version, which is used by Expertiza. We had searched a lot through the Internet, but find very limited useful information on this topic. It doesn't seem reasonable for '''''@user.save''''' still calling the '''''with_scope''''' method, since all versions if Rails, as well as ActiveRecord, are marked as the latest in '''''Gemfile.lock'''''.&lt;br /&gt;
&lt;br /&gt;
=='''Refactor users_controller.rb'''==&lt;br /&gt;
===='''Refactor the “paginate_list” method'''====&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;paginate_list&amp;quot; method is a function in &amp;quot;users_controller.rb&amp;quot;. It will be called if you do search in Manage-&amp;gt;Users page. It has two components: search for users, paginate the results.&lt;br /&gt;
&lt;br /&gt;
However, the controller should not know how the information is retrieved. So we would like to refactor this method by seperating it into search method and paginating method. The search method is in model and the paginating method is still in controller.&lt;br /&gt;
&lt;br /&gt;
The code below is the &amp;quot;paginate_list&amp;quot; method in official Expertiza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# For filtering the users list with proper search and pagination.&lt;br /&gt;
def paginate_list(role, user_id, letter)&lt;br /&gt;
  paginate_options = {&amp;quot;1&amp;quot; =&amp;gt; 25, &amp;quot;2&amp;quot; =&amp;gt; 50, &amp;quot;3&amp;quot; =&amp;gt; 100}&lt;br /&gt;
&lt;br /&gt;
  # If the above hash does not have a value for the key,&lt;br /&gt;
  # it means that we need to show all the users on the page&lt;br /&gt;
  #&lt;br /&gt;
  # Just a point to remember, when we use pagination, the&lt;br /&gt;
  # 'users' variable should be an object, not an array&lt;br /&gt;
&lt;br /&gt;
  #The type of condition for the search depends on what the user has selected from the search_by dropdown&lt;br /&gt;
  condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot; #default used when clicking on letters&lt;br /&gt;
  search_filter = letter + '%'&lt;br /&gt;
  @search_by = params[:search_by]&lt;br /&gt;
  if @search_by == '1'  #search by user name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '2' # search by full name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and fullname like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '3' # search by email&lt;br /&gt;
     condition = &amp;quot;(role_id in (?) or id = ?) and email like ?&amp;quot;&lt;br /&gt;
     search_filter = '%' + letter + '%'&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  if (paginate_options[&amp;quot;#{@per_page}&amp;quot;].nil?) #displaying all - no pagination&lt;br /&gt;
    users = User.order('name').where( [condition, role.get_available_roles, user_id, search_filter]).paginate(:page =&amp;gt; params[:page], :per_page =&amp;gt; User.count)&lt;br /&gt;
  else #some pagination is active - use the per_page&lt;br /&gt;
    users = User.page(params[:page]).order('name').per_page(paginate_options[&amp;quot;#{@per_page}&amp;quot;]).where([condition, role.get_available_roles, user_id, search_filter])&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the code we can see that the search method needs four parameters:&lt;br /&gt;
* role: user can only search users below his role&lt;br /&gt;
* user_id: current user id&lt;br /&gt;
* letter: keyword in search&lt;br /&gt;
* search_by: search by user name, full name or email&lt;br /&gt;
&lt;br /&gt;
Base on this, we implemented the search method in &amp;quot;user.rb&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def self.search_users(role, user_id, letter, search_by)&lt;br /&gt;
  if search_by == '1'  #search by user name&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  elsif search_by == '2' # search by full name&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and fullname like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  elsif search_by == '3' # search by email&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and email like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  else #default used when clicking on letters&lt;br /&gt;
    search_filter = letter + '%'&lt;br /&gt;
    users = User.order('name').where( &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;, role.get_available_roles, user_id, search_filter )&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the original &amp;quot;paginate_list&amp;quot; method is modified as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# For filtering the users list with proper search and pagination.&lt;br /&gt;
def paginate_list(role, user_id, letter)&lt;br /&gt;
  paginate_options = {&amp;quot;1&amp;quot; =&amp;gt; 25, &amp;quot;2&amp;quot; =&amp;gt; 50, &amp;quot;3&amp;quot; =&amp;gt; 100}&lt;br /&gt;
&lt;br /&gt;
  # If the above hash does not have a value for the key,&lt;br /&gt;
  # it means that we need to show all the users on the page&lt;br /&gt;
  #&lt;br /&gt;
  # Just a point to remember, when we use pagination, the&lt;br /&gt;
  # 'users' variable should be an object, not an array&lt;br /&gt;
&lt;br /&gt;
  #The type of condition for the search depends on what the user has selected from the search_by dropdown&lt;br /&gt;
  @search_by = params[:search_by]&lt;br /&gt;
&lt;br /&gt;
  # search for corresponding users&lt;br /&gt;
  users = User.search_users(role, user_id, letter, @search_by)&lt;br /&gt;
&lt;br /&gt;
  # paginate&lt;br /&gt;
  if (paginate_options[&amp;quot;#{@per_page}&amp;quot;].nil?) #displaying all - no pagination&lt;br /&gt;
    users = users.paginate(:page =&amp;gt; params[:page], :per_page =&amp;gt; User.count)&lt;br /&gt;
  else #some pagination is active - use the per_page&lt;br /&gt;
    users = users.page(params[:page]).per_page(paginate_options[&amp;quot;#{@per_page}&amp;quot;])&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''New feature: delete users'''==&lt;br /&gt;
&lt;br /&gt;
===='''Design'''====&lt;br /&gt;
&lt;br /&gt;
At the very beginning, we decide to use &amp;quot;Cascading Delete&amp;quot; to delete users. Because there are many relationship between different users. They can be reviewer, reviewee, teaching assistant, and so on.If we have to delete an user, we have to not only delete the record in ''user'' table, but also other related tables.&lt;br /&gt;
&lt;br /&gt;
So, we divide all users into two set, one is '''new users''' without any relationship, the other is the '''old user''' with some relationships. And we find that it is quite easy to achieve the functionality of deleting new users. When deleting old users, we find some problems. Because old users may be a reviewer before and score some assignments. If we delete some old users, the assignments' review scores will be a mess.&lt;br /&gt;
&lt;br /&gt;
After discussing with professor, we decide to deprecate&amp;quot;Cascading Delete&amp;quot;. And we use below algorithm to handle user deletion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS0.png‎  |frame|center|Confirm box flow diagram]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* A user can be deleted if (s)he has not participated in an assignment;&lt;br /&gt;
* If the user is participating in an assignment, the system will ask, “User is participating in k assignments. Delete as a participant in these assignment(s)?”;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS1.png‎  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS2.png‎  |frame|center|Rename confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Rename (javascript calling update method in users_controller.rb);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS3.png‎  |frame|center|Rename success 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS4.png‎  |frame|center|Cannot delete]]&lt;br /&gt;
&lt;br /&gt;
===='''Implementation'''====&lt;br /&gt;
&lt;br /&gt;
We add a '''userDeleteConfirmBox.js''' file to implement this unique confirm box algorithm.&lt;br /&gt;
&lt;br /&gt;
* First, we overwrite the Rails default confirm function.&lt;br /&gt;
 $.rails.allowAction = function(link) {&lt;br /&gt;
   console.log(link.attr('data-relationship'))&lt;br /&gt;
   console.log(link.attr('data-username'))&lt;br /&gt;
   if ((!link.attr('data-confirm')) || (link.attr('data-relationship') &amp;amp;&amp;amp; link.attr('data-relationship') == 'false')) {&lt;br /&gt;
    return true;&lt;br /&gt;
   }&lt;br /&gt;
   $.rails.showConfirmDialog(link);&lt;br /&gt;
   return false;&lt;br /&gt;
 };&lt;br /&gt;
 $.rails.confirmed = function(link) {&lt;br /&gt;
   link.removeAttr('data-confirm');&lt;br /&gt;
   return link.trigger('click.rails');&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* Then, we write code to achieve customed confirm box using our own algorithm.&lt;br /&gt;
 $.rails.showConfirmDialog = function(link) {&lt;br /&gt;
  var message = link.attr('data-confirm');&lt;br /&gt;
  //confirmation box style&lt;br /&gt;
  $(function() {&lt;br /&gt;
    $(html1).modal();&lt;br /&gt;
    $(&amp;quot;#dialog-confirm1&amp;quot;).dialog({&lt;br /&gt;
      width: 340,&lt;br /&gt;
      buttons: {&lt;br /&gt;
        &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          location.reload();&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;Yes&amp;quot;: function() {&lt;br /&gt;
          //return $.rails.confirmed(link);&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          $(html2).modal();&lt;br /&gt;
          $(&amp;quot;#dialog-confirm2&amp;quot;).dialog({&lt;br /&gt;
            width: 340,&lt;br /&gt;
            buttons: {&lt;br /&gt;
              &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
                $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;Yes&amp;quot;: function() {                 &lt;br /&gt;
                    $('#rename').click() &lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html3).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm3&amp;quot;).dialog({&lt;br /&gt;
                    width: 340,&lt;br /&gt;
                  });&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;No, delete any way!&amp;quot;: function() {&lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html4).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm4&amp;quot;).dialog({&lt;br /&gt;
                      width: 340,&lt;br /&gt;
                      buttons: {&lt;br /&gt;
                        &amp;quot;Close&amp;quot;: function() {&lt;br /&gt;
                          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                          location.reload();&lt;br /&gt;
                        }&lt;br /&gt;
                      }&lt;br /&gt;
                  });&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
           });&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     });&lt;br /&gt;
  });&lt;br /&gt;
  return $('#dialog-confirm .confirm').on('click', function() {&lt;br /&gt;
    return $.rails.confirmed(link);&lt;br /&gt;
  });&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* After that, we all the if condition in '''/users/show.html.erb''' file. So when deleting the old users, Expertiza uses the functionality and customed confirm box we define; when deleting the new users, Expertiza will use the default confirm box.&lt;br /&gt;
  &amp;lt;% if @assignment_participant_num != 0 and (!@maps.nil? or @maps.length != 0)%&amp;gt; &lt;br /&gt;
      &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User is participating in #{@assignment_participant_num} assignments.&amp;lt;br/&amp;gt;Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'true', :username =&amp;gt; @user.name}, :method =&amp;gt; :delete, remote: true%&amp;gt;   &lt;br /&gt;
  &amp;lt;% else %&amp;gt;&lt;br /&gt;
       &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User joins in #{@assignment_participant_num} assignment(s), but without participates in&lt;br /&gt;
 any assignments. Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'false'}, :method =&amp;gt; :delete, remote: true%&amp;gt;&lt;br /&gt;
   &amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Testing feature: search for users'''==&lt;br /&gt;
&lt;br /&gt;
==='''Design'''===&lt;br /&gt;
&lt;br /&gt;
We write some features test to test &amp;quot;search for users&amp;quot; functionality.&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users bylogin names&lt;br /&gt;
 feature 'Method 1: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by login name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'student'&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Student, Perfect&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;pstudent@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by first name or last name&lt;br /&gt;
 feature 'Method2: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by last or first name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'Bob'&lt;br /&gt;
    find('#search_by').select 'Full name'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by email&lt;br /&gt;
 feature 'Method3: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by email' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'bdole@dev.null'&lt;br /&gt;
    find('#search_by').select 'Email'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor deletes new users&lt;br /&gt;
 feature 'Instructor delete a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'which has no relationship' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    #in order to show whole user list&lt;br /&gt;
    fill_in 'letter', with: ''&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    click_link 'student'&lt;br /&gt;
    click_link 'Delete'&lt;br /&gt;
    expect(page).to_not have_content(&amp;quot;student&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;instructor&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==='''Implementation'''===&lt;br /&gt;
 rspec spec/features/users_spec.rb&lt;br /&gt;
&lt;br /&gt;
[[File:Rspec1.png‎  |frame|center|Rspec feature test pass]]&lt;br /&gt;
&lt;br /&gt;
=='''References'''==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95312</id>
		<title>CSC/ECE 517 Spring 2015/oss E1506 SYZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95312"/>
		<updated>2015-03-22T01:56:22Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Delete Uncalled Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;E1506: Refactoring, testing and new features related to “users”&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Overview'''==&lt;br /&gt;
===Code refactoring===&lt;br /&gt;
''Refactoring'' is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior&amp;lt;ref&amp;gt;[http://refactoring.com/ Refactoring]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Refactoring adds to the value of any program that has at least one of the following shortcomings&amp;lt;ref&amp;gt;[http://jexp.de/papers/refactoring/refactoring/node9.html#SECTION00330000000000000000 Benefits of Code Refactoring] Michael Hunger. Oct. 25, 2000&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Programs that are hard to read are hard to modify;&lt;br /&gt;
* Programs that have duplicate logic are hard to modify;&lt;br /&gt;
* Programs that require additional behavior that requires you to change running code are hard to modify;&lt;br /&gt;
* Programs with complex conditional logic are hard to modify.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rspec===&lt;br /&gt;
RSpec is a [http://en.wikipedia.org/wiki/Behavior-driven_development behavior-driven development] (BDD) framework for the [http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby programming language], inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock. The framework can be considered a [http://en.wikipedia.org/wiki/Domain-specific_language domain-specific language] (DSL) and resembles a natural language specification&amp;lt;ref&amp;gt;[http://en.wikipedia.org/wiki/RSpec#cite_note-origin-4g Rspec]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Object-oriented Design Principles===&lt;br /&gt;
Object-oriented programming (OOP) is a programming language model organized around objects rather than &amp;quot;actions&amp;quot; and data rather than logic&amp;lt;ref&amp;gt;[http://searchsoa.techtarget.com/definition/object-oriented-programming Margaret Rouse. ''object-oriented programming (OOP) definition''. Aug 3, 2008]&amp;lt;/ref&amp;gt;. Historically, a program has been viewed as a logical procedure that takes input data, processes it, and produces output data. Though an Object oriented language provides us with highly useful and important programming concepts like '''Inheritance''', '''Polymorphism''', '''Abstraction''' and '''Encapsulation''' which definitely makes the code more efficient, it is equally important to have the knowledge of using them in the code. &lt;br /&gt;
''Object Oriented Design'' Principles are core of OOPS programming&amp;lt;ref&amp;gt;[http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-principles.html#ixzz3Ha8L3cfz Javin Paul. ''Blogspot''. March 3, 2012]&amp;lt;/ref&amp;gt;. It is important to know these design principles, to create clean and modular design. There are many design principles that help us to create clean and efficient code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=='''Project Resources'''==&lt;br /&gt;
* [https://github.com/CSC517-Proj2-E1506/expertiza GitHub Repository]&lt;br /&gt;
* [http://152.46.16.178:3001/ VCL IP] (Log in as user2/password. Go to [http://152.46.16.178:3001/analytic/index VCL analytic page])&lt;br /&gt;
* [https://github.com/expertiza/expertiza/pull/505 GitHub Pull Request Link]&lt;br /&gt;
&lt;br /&gt;
=='''Todo List'''==&lt;br /&gt;
&amp;lt;b&amp;gt;Related files:&amp;lt;/b&amp;gt; users_controller.rb, participants_controller.rb, user.rb, users/show.html.erb&lt;br /&gt;
*  Find the un-called methods if any and delete them. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*  Change the Rails 2 syntax to Rails 4 style.&lt;br /&gt;
*  Refactor users_controller.rb&lt;br /&gt;
** Change the white space for the second harf of this file, starts at “def edit”. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Separate the “paginate_list” method into two methods. The search method should be in model and the paginating method should be in the controller.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* New feature: delete users&lt;br /&gt;
** A user can be deleted if (s)he has not participated in an assignment. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user is participating in an assignment, the system will ask, “User is participating in k assignments.  Delete as a participant in these assignment(s)?”  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden.&lt;br /&gt;
*** rename (javascript calling update method in users_controller.rb) &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*** different users have different delete methods.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Write tests (with Rspec) for this feature.&amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* Testing feature: search for users&lt;br /&gt;
** In rails 4 branch, admins can search for the users with 1) users’ login names 2) users’ last or first names and 3) users’ emails. Please write tests (with Rspec) for this feature &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Delete Uncalled Methods'''==&lt;br /&gt;
The primary way we find unused method is right-click on each method's name, then choose &amp;quot;Find Usages&amp;quot;, as the following picture shows:&lt;br /&gt;
[[File:FindUsages.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then the finding results will be displayed in the bottom, as the following picture shows:&lt;br /&gt;
[[File:FindResult.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In this way we identified the following method from '''''UserController.rb''''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def self.participants_in(assignment_id)&lt;br /&gt;
 users = Array.new&lt;br /&gt;
 participants = AssignmentParticipant.find_by_parent_id(assignment_id)&lt;br /&gt;
 participants.each{&lt;br /&gt;
   |participant|&lt;br /&gt;
   users &amp;lt;&amp;lt; User.find(participant.user_id)&lt;br /&gt;
 }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the following methods from '''''User.rb'''''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def assign_random_password&lt;br /&gt;
 if self.password.blank?&lt;br /&gt;
   self.password = self.random_password&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def self.random_password(size=8)&lt;br /&gt;
 random_pronouncable_password((size/2).round) + rand.to_s[2,3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def get_author_name&lt;br /&gt;
 return self.fullname&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, there's one method in '''''User.rb''''' that has no usage found, but contributes to Expertiza function and thus cannot be deleted. Here's the function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def salt_first?&lt;br /&gt;
    true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Change Rails 2 syntax to Rails 4'''==&lt;br /&gt;
&amp;lt;b&amp;gt;'''with_scope'''&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Refactor users_controller.rb'''==&lt;br /&gt;
===='''Refactor the “paginate_list” method'''====&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;paginate_list&amp;quot; method is a function in &amp;quot;user_controller.rb&amp;quot;. It will be called if you do search in Manage-&amp;gt;Users page. It has two components: search for users, paginate the results.&lt;br /&gt;
&lt;br /&gt;
However, the controller should not know how the information is retrieved. So we would like to refactor this method by seperating it into search method and paginating method. The search method is in model and the paginating method is still in controller.&lt;br /&gt;
&lt;br /&gt;
The code below is the &amp;quot;paginate_list&amp;quot; method in official Expertiza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# For filtering the users list with proper search and pagination.&lt;br /&gt;
def paginate_list(role, user_id, letter)&lt;br /&gt;
  paginate_options = {&amp;quot;1&amp;quot; =&amp;gt; 25, &amp;quot;2&amp;quot; =&amp;gt; 50, &amp;quot;3&amp;quot; =&amp;gt; 100}&lt;br /&gt;
&lt;br /&gt;
  # If the above hash does not have a value for the key,&lt;br /&gt;
  # it means that we need to show all the users on the page&lt;br /&gt;
  #&lt;br /&gt;
  # Just a point to remember, when we use pagination, the&lt;br /&gt;
  # 'users' variable should be an object, not an array&lt;br /&gt;
&lt;br /&gt;
  #The type of condition for the search depends on what the user has selected from the search_by dropdown&lt;br /&gt;
  condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot; #default used when clicking on letters&lt;br /&gt;
  search_filter = letter + '%'&lt;br /&gt;
  @search_by = params[:search_by]&lt;br /&gt;
  if @search_by == '1'  #search by user name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '2' # search by full name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and fullname like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '3' # search by email&lt;br /&gt;
     condition = &amp;quot;(role_id in (?) or id = ?) and email like ?&amp;quot;&lt;br /&gt;
     search_filter = '%' + letter + '%'&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  if (paginate_options[&amp;quot;#{@per_page}&amp;quot;].nil?) #displaying all - no pagination&lt;br /&gt;
    users = User.order('name').where( [condition, role.get_available_roles, user_id, search_filter]).paginate(:page =&amp;gt; params[:page], :per_page =&amp;gt; User.count)&lt;br /&gt;
    else #some pagination is active - use the per_page&lt;br /&gt;
    users = User.page(params[:page]).order('name').per_page(paginate_options[&amp;quot;#{@per_page}&amp;quot;]).where([condition, role.get_available_roles, user_id, search_filter])&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''New feature: delete users'''==&lt;br /&gt;
&lt;br /&gt;
===='''Design'''====&lt;br /&gt;
&lt;br /&gt;
At the very beginning, we decide to use &amp;quot;Cascading Delete&amp;quot; to delete users. Because there are many relationship between different users. They can be reviewer, reviewee, teaching assistant, and so on.If we have to delete an user, we have to not only delete the record in ''user'' table, but also other related tables.&lt;br /&gt;
&lt;br /&gt;
So, we divide all users into two set, one is '''new users''' without any relationship, the other is the '''old user''' with some relationships. And we find that it is quite easy to achieve the functionality of deleting new users. When deleting old users, we find some problems. Because old users may be a reviewer before and score some assignments. If we delete some old users, the assignments' review scores will be a mess.&lt;br /&gt;
&lt;br /&gt;
After discussing with professor, we decide to deprecate&amp;quot;Cascading Delete&amp;quot;. And we use below algorithm to handle user deletion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS0.png‎  |frame|center|Confirm box flow diagram]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* A user can be deleted if (s)he has not participated in an assignment;&lt;br /&gt;
* If the user is participating in an assignment, the system will ask, “User is participating in k assignments. Delete as a participant in these assignment(s)?”;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS1.png‎  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS2.png‎  |frame|center|Rename confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Rename (javascript calling update method in users_controller.rb);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS3.png‎  |frame|center|Rename success 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS4.png‎  |frame|center|Cannot delete]]&lt;br /&gt;
&lt;br /&gt;
===='''Implementation'''====&lt;br /&gt;
&lt;br /&gt;
We add a '''userDeleteConfirmBox.js''' file to implement this unique confirm box algorithm.&lt;br /&gt;
&lt;br /&gt;
* First, we overwrite the Rails default confirm function.&lt;br /&gt;
 $.rails.allowAction = function(link) {&lt;br /&gt;
   console.log(link.attr('data-relationship'))&lt;br /&gt;
   console.log(link.attr('data-username'))&lt;br /&gt;
   if ((!link.attr('data-confirm')) || (link.attr('data-relationship') &amp;amp;&amp;amp; link.attr('data-relationship') == 'false')) {&lt;br /&gt;
    return true;&lt;br /&gt;
   }&lt;br /&gt;
   $.rails.showConfirmDialog(link);&lt;br /&gt;
   return false;&lt;br /&gt;
 };&lt;br /&gt;
 $.rails.confirmed = function(link) {&lt;br /&gt;
   link.removeAttr('data-confirm');&lt;br /&gt;
   return link.trigger('click.rails');&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* Then, we write code to achieve customed confirm box using our own algorithm.&lt;br /&gt;
 $.rails.showConfirmDialog = function(link) {&lt;br /&gt;
  var message = link.attr('data-confirm');&lt;br /&gt;
  //confirmation box style&lt;br /&gt;
  $(function() {&lt;br /&gt;
    $(html1).modal();&lt;br /&gt;
    $(&amp;quot;#dialog-confirm1&amp;quot;).dialog({&lt;br /&gt;
      width: 340,&lt;br /&gt;
      buttons: {&lt;br /&gt;
        &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          location.reload();&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;Yes&amp;quot;: function() {&lt;br /&gt;
          //return $.rails.confirmed(link);&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          $(html2).modal();&lt;br /&gt;
          $(&amp;quot;#dialog-confirm2&amp;quot;).dialog({&lt;br /&gt;
            width: 340,&lt;br /&gt;
            buttons: {&lt;br /&gt;
              &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
                $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;Yes&amp;quot;: function() {                 &lt;br /&gt;
                    $('#rename').click() &lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html3).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm3&amp;quot;).dialog({&lt;br /&gt;
                    width: 340,&lt;br /&gt;
                  });&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;No, delete any way!&amp;quot;: function() {&lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html4).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm4&amp;quot;).dialog({&lt;br /&gt;
                      width: 340,&lt;br /&gt;
                      buttons: {&lt;br /&gt;
                        &amp;quot;Close&amp;quot;: function() {&lt;br /&gt;
                          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                          location.reload();&lt;br /&gt;
                        }&lt;br /&gt;
                      }&lt;br /&gt;
                  });&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
           });&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     });&lt;br /&gt;
  });&lt;br /&gt;
  return $('#dialog-confirm .confirm').on('click', function() {&lt;br /&gt;
    return $.rails.confirmed(link);&lt;br /&gt;
  });&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* After that, we all the if condition in '''/users/show.html.erb''' file. So when deleting the old users, Expertiza uses the functionality and customed confirm box we define; when deleting the new users, Expertiza will use the default confirm box.&lt;br /&gt;
  &amp;lt;% if @assignment_participant_num != 0 and (!@maps.nil? or @maps.length != 0)%&amp;gt; &lt;br /&gt;
      &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User is participating in #{@assignment_participant_num} assignments.&amp;lt;br/&amp;gt;Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'true', :username =&amp;gt; @user.name}, :method =&amp;gt; :delete, remote: true%&amp;gt;   &lt;br /&gt;
  &amp;lt;% else %&amp;gt;&lt;br /&gt;
       &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User joins in #{@assignment_participant_num} assignment(s), but without participates in&lt;br /&gt;
 any assignments. Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'false'}, :method =&amp;gt; :delete, remote: true%&amp;gt;&lt;br /&gt;
   &amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Testing feature: search for users'''==&lt;br /&gt;
&lt;br /&gt;
==='''Design'''===&lt;br /&gt;
&lt;br /&gt;
We write some features test to test &amp;quot;search for users&amp;quot; functionality.&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users bylogin names&lt;br /&gt;
 feature 'Method 1: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by login name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'student'&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Student, Perfect&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;pstudent@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by first name or last name&lt;br /&gt;
 feature 'Method2: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by last or first name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'Bob'&lt;br /&gt;
    find('#search_by').select 'Full name'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by email&lt;br /&gt;
 feature 'Method3: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by email' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'bdole@dev.null'&lt;br /&gt;
    find('#search_by').select 'Email'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor deletes new users&lt;br /&gt;
 feature 'Instructor delete a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'which has no relationship' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    #in order to show whole user list&lt;br /&gt;
    fill_in 'letter', with: ''&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    click_link 'student'&lt;br /&gt;
    click_link 'Delete'&lt;br /&gt;
    expect(page).to_not have_content(&amp;quot;student&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;instructor&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==='''Implement'''===&lt;br /&gt;
 rspec spec/features/users_spec.rb&lt;br /&gt;
&lt;br /&gt;
[[File:Rspec1.png‎  |frame|center|Rspec feature test pass]]&lt;br /&gt;
&lt;br /&gt;
=='''References'''==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95311</id>
		<title>CSC/ECE 517 Spring 2015/oss E1506 SYZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95311"/>
		<updated>2015-03-22T01:53:02Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Delete Uncalled Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;E1506: Refactoring, testing and new features related to “users”&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Overview'''==&lt;br /&gt;
===Code refactoring===&lt;br /&gt;
''Refactoring'' is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior&amp;lt;ref&amp;gt;[http://refactoring.com/ Refactoring]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Refactoring adds to the value of any program that has at least one of the following shortcomings&amp;lt;ref&amp;gt;[http://jexp.de/papers/refactoring/refactoring/node9.html#SECTION00330000000000000000 Benefits of Code Refactoring] Michael Hunger. Oct. 25, 2000&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Programs that are hard to read are hard to modify;&lt;br /&gt;
* Programs that have duplicate logic are hard to modify;&lt;br /&gt;
* Programs that require additional behavior that requires you to change running code are hard to modify;&lt;br /&gt;
* Programs with complex conditional logic are hard to modify.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rspec===&lt;br /&gt;
RSpec is a [http://en.wikipedia.org/wiki/Behavior-driven_development behavior-driven development] (BDD) framework for the [http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby programming language], inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock. The framework can be considered a [http://en.wikipedia.org/wiki/Domain-specific_language domain-specific language] (DSL) and resembles a natural language specification&amp;lt;ref&amp;gt;[http://en.wikipedia.org/wiki/RSpec#cite_note-origin-4g Rspec]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Object-oriented Design Principles===&lt;br /&gt;
Object-oriented programming (OOP) is a programming language model organized around objects rather than &amp;quot;actions&amp;quot; and data rather than logic&amp;lt;ref&amp;gt;[http://searchsoa.techtarget.com/definition/object-oriented-programming Margaret Rouse. ''object-oriented programming (OOP) definition''. Aug 3, 2008]&amp;lt;/ref&amp;gt;. Historically, a program has been viewed as a logical procedure that takes input data, processes it, and produces output data. Though an Object oriented language provides us with highly useful and important programming concepts like '''Inheritance''', '''Polymorphism''', '''Abstraction''' and '''Encapsulation''' which definitely makes the code more efficient, it is equally important to have the knowledge of using them in the code. &lt;br /&gt;
''Object Oriented Design'' Principles are core of OOPS programming&amp;lt;ref&amp;gt;[http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-principles.html#ixzz3Ha8L3cfz Javin Paul. ''Blogspot''. March 3, 2012]&amp;lt;/ref&amp;gt;. It is important to know these design principles, to create clean and modular design. There are many design principles that help us to create clean and efficient code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=='''Project Resources'''==&lt;br /&gt;
* [https://github.com/CSC517-Proj2-E1506/expertiza GitHub Repository]&lt;br /&gt;
* [http://152.46.16.178:3001/ VCL IP] (Log in as user2/password. Go to [http://152.46.16.178:3001/analytic/index VCL analytic page])&lt;br /&gt;
* [https://github.com/expertiza/expertiza/pull/505 GitHub Pull Request Link]&lt;br /&gt;
&lt;br /&gt;
=='''Todo List'''==&lt;br /&gt;
&amp;lt;b&amp;gt;Related files:&amp;lt;/b&amp;gt; users_controller.rb, participants_controller.rb, user.rb, users/show.html.erb&lt;br /&gt;
*  Find the un-called methods if any and delete them. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*  Change the Rails 2 syntax to Rails 4 style.&lt;br /&gt;
*  Refactor users_controller.rb&lt;br /&gt;
** Change the white space for the second harf of this file, starts at “def edit”. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Separate the “paginate_list” method into two methods. The search method should be in model and the paginating method should be in the controller.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* New feature: delete users&lt;br /&gt;
** A user can be deleted if (s)he has not participated in an assignment. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user is participating in an assignment, the system will ask, “User is participating in k assignments.  Delete as a participant in these assignment(s)?”  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden.&lt;br /&gt;
*** rename (javascript calling update method in users_controller.rb) &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*** different users have different delete methods.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Write tests (with Rspec) for this feature.&amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* Testing feature: search for users&lt;br /&gt;
** In rails 4 branch, admins can search for the users with 1) users’ login names 2) users’ last or first names and 3) users’ emails. Please write tests (with Rspec) for this feature &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Delete Uncalled Methods'''==&lt;br /&gt;
The primary way we find unused method is right-click on each method's name, then choose &amp;quot;Find Usage&amp;quot;, as the following picture shows:&lt;br /&gt;
[[File:FindUsages.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then the finding results will be displayed in the bottom, as the following picture shows:&lt;br /&gt;
[[File:FindResult.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In this way we identified the following method from '''''UserController.rb''''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def self.participants_in(assignment_id)&lt;br /&gt;
 users = Array.new&lt;br /&gt;
 participants = AssignmentParticipant.find_by_parent_id(assignment_id)&lt;br /&gt;
 participants.each{&lt;br /&gt;
   |participant|&lt;br /&gt;
   users &amp;lt;&amp;lt; User.find(participant.user_id)&lt;br /&gt;
 }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the following methods from '''''User.rb'''''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def assign_random_password&lt;br /&gt;
 if self.password.blank?&lt;br /&gt;
   self.password = self.random_password&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def self.random_password(size=8)&lt;br /&gt;
 random_pronouncable_password((size/2).round) + rand.to_s[2,3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def get_author_name&lt;br /&gt;
 return self.fullname&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Change Rails 2 syntax to Rails 4'''==&lt;br /&gt;
&amp;lt;b&amp;gt;'''with_scope'''&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Refactor users_controller.rb'''==&lt;br /&gt;
===='''Refactor the “paginate_list” method'''====&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;paginate_list&amp;quot; method is a function in &amp;quot;user_controller.rb&amp;quot;. It will be called if you do search in Manage-&amp;gt;Users page. It has two components: search for users, paginate the results.&lt;br /&gt;
&lt;br /&gt;
However, the controller should not know how the information is retrieved. So we would like to refactor this method by seperating it into search method and paginating method. The search method is in model and the paginating method is still in controller.&lt;br /&gt;
&lt;br /&gt;
The code below is the &amp;quot;paginate_list&amp;quot; method in official Expertiza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# For filtering the users list with proper search and pagination.&lt;br /&gt;
def paginate_list(role, user_id, letter)&lt;br /&gt;
  paginate_options = {&amp;quot;1&amp;quot; =&amp;gt; 25, &amp;quot;2&amp;quot; =&amp;gt; 50, &amp;quot;3&amp;quot; =&amp;gt; 100}&lt;br /&gt;
&lt;br /&gt;
  # If the above hash does not have a value for the key,&lt;br /&gt;
  # it means that we need to show all the users on the page&lt;br /&gt;
  #&lt;br /&gt;
  # Just a point to remember, when we use pagination, the&lt;br /&gt;
  # 'users' variable should be an object, not an array&lt;br /&gt;
&lt;br /&gt;
  #The type of condition for the search depends on what the user has selected from the search_by dropdown&lt;br /&gt;
  condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot; #default used when clicking on letters&lt;br /&gt;
  search_filter = letter + '%'&lt;br /&gt;
  @search_by = params[:search_by]&lt;br /&gt;
  if @search_by == '1'  #search by user name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '2' # search by full name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and fullname like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '3' # search by email&lt;br /&gt;
     condition = &amp;quot;(role_id in (?) or id = ?) and email like ?&amp;quot;&lt;br /&gt;
     search_filter = '%' + letter + '%'&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  if (paginate_options[&amp;quot;#{@per_page}&amp;quot;].nil?) #displaying all - no pagination&lt;br /&gt;
    users = User.order('name').where( [condition, role.get_available_roles, user_id, search_filter]).paginate(:page =&amp;gt; params[:page], :per_page =&amp;gt; User.count)&lt;br /&gt;
    else #some pagination is active - use the per_page&lt;br /&gt;
    users = User.page(params[:page]).order('name').per_page(paginate_options[&amp;quot;#{@per_page}&amp;quot;]).where([condition, role.get_available_roles, user_id, search_filter])&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''New feature: delete users'''==&lt;br /&gt;
&lt;br /&gt;
===='''Design'''====&lt;br /&gt;
&lt;br /&gt;
At the very beginning, we decide to use &amp;quot;Cascading Delete&amp;quot; to delete users. Because there are many relationship between different users. They can be reviewer, reviewee, teaching assistant, and so on.If we have to delete an user, we have to not only delete the record in ''user'' table, but also other related tables.&lt;br /&gt;
&lt;br /&gt;
So, we divide all users into two set, one is '''new users''' without any relationship, the other is the '''old user''' with some relationships. And we find that it is quite easy to achieve the functionality of deleting new users. When deleting old users, we find some problems. Because old users may be a reviewer before and score some assignments. If we delete some old users, the assignments' review scores will be a mess.&lt;br /&gt;
&lt;br /&gt;
After discussing with professor, we decide to deprecate&amp;quot;Cascading Delete&amp;quot;. And we use below algorithm to handle user deletion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS0.png‎  |frame|center|Confirm box flow diagram]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* A user can be deleted if (s)he has not participated in an assignment;&lt;br /&gt;
* If the user is participating in an assignment, the system will ask, “User is participating in k assignments. Delete as a participant in these assignment(s)?”;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS1.png‎  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS2.png‎  |frame|center|Rename confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Rename (javascript calling update method in users_controller.rb);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS3.png‎  |frame|center|Rename success 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS4.png‎  |frame|center|Cannot delete]]&lt;br /&gt;
&lt;br /&gt;
===='''Implementation'''====&lt;br /&gt;
&lt;br /&gt;
We add a '''userDeleteConfirmBox.js''' file to implement this unique confirm box algorithm.&lt;br /&gt;
&lt;br /&gt;
* First, we overwrite the Rails default confirm function.&lt;br /&gt;
 $.rails.allowAction = function(link) {&lt;br /&gt;
   console.log(link.attr('data-relationship'))&lt;br /&gt;
   console.log(link.attr('data-username'))&lt;br /&gt;
   if ((!link.attr('data-confirm')) || (link.attr('data-relationship') &amp;amp;&amp;amp; link.attr('data-relationship') == 'false')) {&lt;br /&gt;
    return true;&lt;br /&gt;
   }&lt;br /&gt;
   $.rails.showConfirmDialog(link);&lt;br /&gt;
   return false;&lt;br /&gt;
 };&lt;br /&gt;
 $.rails.confirmed = function(link) {&lt;br /&gt;
   link.removeAttr('data-confirm');&lt;br /&gt;
   return link.trigger('click.rails');&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* Then, we write code to achieve customed confirm box using our own algorithm.&lt;br /&gt;
 $.rails.showConfirmDialog = function(link) {&lt;br /&gt;
  var message = link.attr('data-confirm');&lt;br /&gt;
  //confirmation box style&lt;br /&gt;
  $(function() {&lt;br /&gt;
    $(html1).modal();&lt;br /&gt;
    $(&amp;quot;#dialog-confirm1&amp;quot;).dialog({&lt;br /&gt;
      width: 340,&lt;br /&gt;
      buttons: {&lt;br /&gt;
        &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          location.reload();&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;Yes&amp;quot;: function() {&lt;br /&gt;
          //return $.rails.confirmed(link);&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          $(html2).modal();&lt;br /&gt;
          $(&amp;quot;#dialog-confirm2&amp;quot;).dialog({&lt;br /&gt;
            width: 340,&lt;br /&gt;
            buttons: {&lt;br /&gt;
              &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
                $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;Yes&amp;quot;: function() {                 &lt;br /&gt;
                    $('#rename').click() &lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html3).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm3&amp;quot;).dialog({&lt;br /&gt;
                    width: 340,&lt;br /&gt;
                  });&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;No, delete any way!&amp;quot;: function() {&lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html4).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm4&amp;quot;).dialog({&lt;br /&gt;
                      width: 340,&lt;br /&gt;
                      buttons: {&lt;br /&gt;
                        &amp;quot;Close&amp;quot;: function() {&lt;br /&gt;
                          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                          location.reload();&lt;br /&gt;
                        }&lt;br /&gt;
                      }&lt;br /&gt;
                  });&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
           });&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     });&lt;br /&gt;
  });&lt;br /&gt;
  return $('#dialog-confirm .confirm').on('click', function() {&lt;br /&gt;
    return $.rails.confirmed(link);&lt;br /&gt;
  });&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* After that, we all the if condition in '''/users/show.html.erb''' file. So when deleting the old users, Expertiza uses the functionality and customed confirm box we define; when deleting the new users, Expertiza will use the default confirm box.&lt;br /&gt;
  &amp;lt;% if @assignment_participant_num != 0 and (!@maps.nil? or @maps.length != 0)%&amp;gt; &lt;br /&gt;
      &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User is participating in #{@assignment_participant_num} assignments.&amp;lt;br/&amp;gt;Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'true', :username =&amp;gt; @user.name}, :method =&amp;gt; :delete, remote: true%&amp;gt;   &lt;br /&gt;
  &amp;lt;% else %&amp;gt;&lt;br /&gt;
       &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User joins in #{@assignment_participant_num} assignment(s), but without participates in&lt;br /&gt;
 any assignments. Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'false'}, :method =&amp;gt; :delete, remote: true%&amp;gt;&lt;br /&gt;
   &amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Testing feature: search for users'''==&lt;br /&gt;
&lt;br /&gt;
==='''Design'''===&lt;br /&gt;
&lt;br /&gt;
We write some features test to test &amp;quot;search for users&amp;quot; functionality.&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users bylogin names&lt;br /&gt;
 feature 'Method 1: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by login name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'student'&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Student, Perfect&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;pstudent@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by first name or last name&lt;br /&gt;
 feature 'Method2: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by last or first name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'Bob'&lt;br /&gt;
    find('#search_by').select 'Full name'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by email&lt;br /&gt;
 feature 'Method3: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by email' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'bdole@dev.null'&lt;br /&gt;
    find('#search_by').select 'Email'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor deletes new users&lt;br /&gt;
 feature 'Instructor delete a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'which has no relationship' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    #in order to show whole user list&lt;br /&gt;
    fill_in 'letter', with: ''&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    click_link 'student'&lt;br /&gt;
    click_link 'Delete'&lt;br /&gt;
    expect(page).to_not have_content(&amp;quot;student&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;instructor&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==='''Implement'''===&lt;br /&gt;
 rspec spec/features/users_spec.rb&lt;br /&gt;
&lt;br /&gt;
[[File:Rspec1.png‎  |frame|center|Rspec feature test pass]]&lt;br /&gt;
&lt;br /&gt;
=='''References'''==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95310</id>
		<title>CSC/ECE 517 Spring 2015/oss E1506 SYZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95310"/>
		<updated>2015-03-22T01:51:55Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Delete Uncalled Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;E1506: Refactoring, testing and new features related to “users”&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Overview'''==&lt;br /&gt;
===Code refactoring===&lt;br /&gt;
''Refactoring'' is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior&amp;lt;ref&amp;gt;[http://refactoring.com/ Refactoring]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Refactoring adds to the value of any program that has at least one of the following shortcomings&amp;lt;ref&amp;gt;[http://jexp.de/papers/refactoring/refactoring/node9.html#SECTION00330000000000000000 Benefits of Code Refactoring] Michael Hunger. Oct. 25, 2000&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Programs that are hard to read are hard to modify;&lt;br /&gt;
* Programs that have duplicate logic are hard to modify;&lt;br /&gt;
* Programs that require additional behavior that requires you to change running code are hard to modify;&lt;br /&gt;
* Programs with complex conditional logic are hard to modify.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rspec===&lt;br /&gt;
RSpec is a [http://en.wikipedia.org/wiki/Behavior-driven_development behavior-driven development] (BDD) framework for the [http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby programming language], inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock. The framework can be considered a [http://en.wikipedia.org/wiki/Domain-specific_language domain-specific language] (DSL) and resembles a natural language specification&amp;lt;ref&amp;gt;[http://en.wikipedia.org/wiki/RSpec#cite_note-origin-4g Rspec]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Object-oriented Design Principles===&lt;br /&gt;
Object-oriented programming (OOP) is a programming language model organized around objects rather than &amp;quot;actions&amp;quot; and data rather than logic&amp;lt;ref&amp;gt;[http://searchsoa.techtarget.com/definition/object-oriented-programming Margaret Rouse. ''object-oriented programming (OOP) definition''. Aug 3, 2008]&amp;lt;/ref&amp;gt;. Historically, a program has been viewed as a logical procedure that takes input data, processes it, and produces output data. Though an Object oriented language provides us with highly useful and important programming concepts like '''Inheritance''', '''Polymorphism''', '''Abstraction''' and '''Encapsulation''' which definitely makes the code more efficient, it is equally important to have the knowledge of using them in the code. &lt;br /&gt;
''Object Oriented Design'' Principles are core of OOPS programming&amp;lt;ref&amp;gt;[http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-principles.html#ixzz3Ha8L3cfz Javin Paul. ''Blogspot''. March 3, 2012]&amp;lt;/ref&amp;gt;. It is important to know these design principles, to create clean and modular design. There are many design principles that help us to create clean and efficient code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=='''Project Resources'''==&lt;br /&gt;
* [https://github.com/CSC517-Proj2-E1506/expertiza GitHub Repository]&lt;br /&gt;
* [http://152.46.16.178:3001/ VCL IP] (Log in as user2/password. Go to [http://152.46.16.178:3001/analytic/index VCL analytic page])&lt;br /&gt;
* [https://github.com/expertiza/expertiza/pull/505 GitHub Pull Request Link]&lt;br /&gt;
&lt;br /&gt;
=='''Todo List'''==&lt;br /&gt;
&amp;lt;b&amp;gt;Related files:&amp;lt;/b&amp;gt; users_controller.rb, participants_controller.rb, user.rb, users/show.html.erb&lt;br /&gt;
*  Find the un-called methods if any and delete them. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*  Change the Rails 2 syntax to Rails 4 style.&lt;br /&gt;
*  Refactor users_controller.rb&lt;br /&gt;
** Change the white space for the second harf of this file, starts at “def edit”. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Separate the “paginate_list” method into two methods. The search method should be in model and the paginating method should be in the controller.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* New feature: delete users&lt;br /&gt;
** A user can be deleted if (s)he has not participated in an assignment. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user is participating in an assignment, the system will ask, “User is participating in k assignments.  Delete as a participant in these assignment(s)?”  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden.&lt;br /&gt;
*** rename (javascript calling update method in users_controller.rb) &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*** different users have different delete methods.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Write tests (with Rspec) for this feature.&amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* Testing feature: search for users&lt;br /&gt;
** In rails 4 branch, admins can search for the users with 1) users’ login names 2) users’ last or first names and 3) users’ emails. Please write tests (with Rspec) for this feature &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Delete Uncalled Methods'''==&lt;br /&gt;
The primary way we find unused method is right-click on each method's name, then choose &amp;quot;Find Usage&amp;quot;, as the following picture shows:&lt;br /&gt;
[[File:FindUsages.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then the finding results will be displayed in the bottom, as the following picture shows:&lt;br /&gt;
[[File:FindResult.PNG  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In this way we identified the following method from '''''UserController.rb''''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def self.participants_in(assignment_id)&lt;br /&gt;
 users = Array.new&lt;br /&gt;
 participants = AssignmentParticipant.find_by_parent_id(assignment_id)&lt;br /&gt;
 participants.each{&lt;br /&gt;
   |participant|&lt;br /&gt;
   users &amp;lt;&amp;lt; User.find(participant.user_id)&lt;br /&gt;
 }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the following methods from '''''User.rb'''''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def assign_random_password&lt;br /&gt;
 if self.password.blank?&lt;br /&gt;
   self.password = self.random_password&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def self.random_password(size=8)&lt;br /&gt;
 random_pronouncable_password((size/2).round) + rand.to_s[2,3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def get_author_name&lt;br /&gt;
 	  return self.fullname&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Change Rails 2 syntax to Rails 4'''==&lt;br /&gt;
&amp;lt;b&amp;gt;'''with_scope'''&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Refactor users_controller.rb'''==&lt;br /&gt;
===='''Refactor the “paginate_list” method'''====&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;paginate_list&amp;quot; method is a function in &amp;quot;user_controller.rb&amp;quot;. It will be called if you do search in Manage-&amp;gt;Users page. It has two components: search for users, paginate the results.&lt;br /&gt;
&lt;br /&gt;
However, the controller should not know how the information is retrieved. So we would like to refactor this method by seperating it into search method and paginating method. The search method is in model and the paginating method is still in controller.&lt;br /&gt;
&lt;br /&gt;
The code below is the &amp;quot;paginate_list&amp;quot; method in official Expertiza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# For filtering the users list with proper search and pagination.&lt;br /&gt;
def paginate_list(role, user_id, letter)&lt;br /&gt;
  paginate_options = {&amp;quot;1&amp;quot; =&amp;gt; 25, &amp;quot;2&amp;quot; =&amp;gt; 50, &amp;quot;3&amp;quot; =&amp;gt; 100}&lt;br /&gt;
&lt;br /&gt;
  # If the above hash does not have a value for the key,&lt;br /&gt;
  # it means that we need to show all the users on the page&lt;br /&gt;
  #&lt;br /&gt;
  # Just a point to remember, when we use pagination, the&lt;br /&gt;
  # 'users' variable should be an object, not an array&lt;br /&gt;
&lt;br /&gt;
  #The type of condition for the search depends on what the user has selected from the search_by dropdown&lt;br /&gt;
  condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot; #default used when clicking on letters&lt;br /&gt;
  search_filter = letter + '%'&lt;br /&gt;
  @search_by = params[:search_by]&lt;br /&gt;
  if @search_by == '1'  #search by user name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and name like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '2' # search by full name&lt;br /&gt;
    condition = &amp;quot;(role_id in (?) or id = ?) and fullname like ?&amp;quot;&lt;br /&gt;
    search_filter = '%' + letter + '%'&lt;br /&gt;
  elsif @search_by == '3' # search by email&lt;br /&gt;
     condition = &amp;quot;(role_id in (?) or id = ?) and email like ?&amp;quot;&lt;br /&gt;
     search_filter = '%' + letter + '%'&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  if (paginate_options[&amp;quot;#{@per_page}&amp;quot;].nil?) #displaying all - no pagination&lt;br /&gt;
    users = User.order('name').where( [condition, role.get_available_roles, user_id, search_filter]).paginate(:page =&amp;gt; params[:page], :per_page =&amp;gt; User.count)&lt;br /&gt;
    else #some pagination is active - use the per_page&lt;br /&gt;
    users = User.page(params[:page]).order('name').per_page(paginate_options[&amp;quot;#{@per_page}&amp;quot;]).where([condition, role.get_available_roles, user_id, search_filter])&lt;br /&gt;
  end&lt;br /&gt;
  users&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''New feature: delete users'''==&lt;br /&gt;
&lt;br /&gt;
===='''Design'''====&lt;br /&gt;
&lt;br /&gt;
At the very beginning, we decide to use &amp;quot;Cascading Delete&amp;quot; to delete users. Because there are many relationship between different users. They can be reviewer, reviewee, teaching assistant, and so on.If we have to delete an user, we have to not only delete the record in ''user'' table, but also other related tables.&lt;br /&gt;
&lt;br /&gt;
So, we divide all users into two set, one is '''new users''' without any relationship, the other is the '''old user''' with some relationships. And we find that it is quite easy to achieve the functionality of deleting new users. When deleting old users, we find some problems. Because old users may be a reviewer before and score some assignments. If we delete some old users, the assignments' review scores will be a mess.&lt;br /&gt;
&lt;br /&gt;
After discussing with professor, we decide to deprecate&amp;quot;Cascading Delete&amp;quot;. And we use below algorithm to handle user deletion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS0.png‎  |frame|center|Confirm box flow diagram]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* A user can be deleted if (s)he has not participated in an assignment;&lt;br /&gt;
* If the user is participating in an assignment, the system will ask, “User is participating in k assignments. Delete as a participant in these assignment(s)?”;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS1.png‎  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS2.png‎  |frame|center|Rename confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Rename (javascript calling update method in users_controller.rb);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS3.png‎  |frame|center|Rename success 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS4.png‎  |frame|center|Cannot delete]]&lt;br /&gt;
&lt;br /&gt;
===='''Implementation'''====&lt;br /&gt;
&lt;br /&gt;
We add a '''userDeleteConfirmBox.js''' file to implement this unique confirm box algorithm.&lt;br /&gt;
&lt;br /&gt;
* First, we overwrite the Rails default confirm function.&lt;br /&gt;
 $.rails.allowAction = function(link) {&lt;br /&gt;
   console.log(link.attr('data-relationship'))&lt;br /&gt;
   console.log(link.attr('data-username'))&lt;br /&gt;
   if ((!link.attr('data-confirm')) || (link.attr('data-relationship') &amp;amp;&amp;amp; link.attr('data-relationship') == 'false')) {&lt;br /&gt;
    return true;&lt;br /&gt;
   }&lt;br /&gt;
   $.rails.showConfirmDialog(link);&lt;br /&gt;
   return false;&lt;br /&gt;
 };&lt;br /&gt;
 $.rails.confirmed = function(link) {&lt;br /&gt;
   link.removeAttr('data-confirm');&lt;br /&gt;
   return link.trigger('click.rails');&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* Then, we write code to achieve customed confirm box using our own algorithm.&lt;br /&gt;
 $.rails.showConfirmDialog = function(link) {&lt;br /&gt;
  var message = link.attr('data-confirm');&lt;br /&gt;
  //confirmation box style&lt;br /&gt;
  $(function() {&lt;br /&gt;
    $(html1).modal();&lt;br /&gt;
    $(&amp;quot;#dialog-confirm1&amp;quot;).dialog({&lt;br /&gt;
      width: 340,&lt;br /&gt;
      buttons: {&lt;br /&gt;
        &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          location.reload();&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;Yes&amp;quot;: function() {&lt;br /&gt;
          //return $.rails.confirmed(link);&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          $(html2).modal();&lt;br /&gt;
          $(&amp;quot;#dialog-confirm2&amp;quot;).dialog({&lt;br /&gt;
            width: 340,&lt;br /&gt;
            buttons: {&lt;br /&gt;
              &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
                $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;Yes&amp;quot;: function() {                 &lt;br /&gt;
                    $('#rename').click() &lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html3).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm3&amp;quot;).dialog({&lt;br /&gt;
                    width: 340,&lt;br /&gt;
                  });&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;No, delete any way!&amp;quot;: function() {&lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html4).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm4&amp;quot;).dialog({&lt;br /&gt;
                      width: 340,&lt;br /&gt;
                      buttons: {&lt;br /&gt;
                        &amp;quot;Close&amp;quot;: function() {&lt;br /&gt;
                          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                          location.reload();&lt;br /&gt;
                        }&lt;br /&gt;
                      }&lt;br /&gt;
                  });&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
           });&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     });&lt;br /&gt;
  });&lt;br /&gt;
  return $('#dialog-confirm .confirm').on('click', function() {&lt;br /&gt;
    return $.rails.confirmed(link);&lt;br /&gt;
  });&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* After that, we all the if condition in '''/users/show.html.erb''' file. So when deleting the old users, Expertiza uses the functionality and customed confirm box we define; when deleting the new users, Expertiza will use the default confirm box.&lt;br /&gt;
  &amp;lt;% if @assignment_participant_num != 0 and (!@maps.nil? or @maps.length != 0)%&amp;gt; &lt;br /&gt;
      &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User is participating in #{@assignment_participant_num} assignments.&amp;lt;br/&amp;gt;Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'true', :username =&amp;gt; @user.name}, :method =&amp;gt; :delete, remote: true%&amp;gt;   &lt;br /&gt;
  &amp;lt;% else %&amp;gt;&lt;br /&gt;
       &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User joins in #{@assignment_participant_num} assignment(s), but without participates in&lt;br /&gt;
 any assignments. Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'false'}, :method =&amp;gt; :delete, remote: true%&amp;gt;&lt;br /&gt;
   &amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Testing feature: search for users'''==&lt;br /&gt;
&lt;br /&gt;
==='''Design'''===&lt;br /&gt;
&lt;br /&gt;
We write some features test to test &amp;quot;search for users&amp;quot; functionality.&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users bylogin names&lt;br /&gt;
 feature 'Method 1: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by login name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'student'&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Student, Perfect&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;pstudent@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by first name or last name&lt;br /&gt;
 feature 'Method2: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by last or first name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'Bob'&lt;br /&gt;
    find('#search_by').select 'Full name'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by email&lt;br /&gt;
 feature 'Method3: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by email' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'bdole@dev.null'&lt;br /&gt;
    find('#search_by').select 'Email'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor deletes new users&lt;br /&gt;
 feature 'Instructor delete a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'which has no relationship' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    #in order to show whole user list&lt;br /&gt;
    fill_in 'letter', with: ''&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    click_link 'student'&lt;br /&gt;
    click_link 'Delete'&lt;br /&gt;
    expect(page).to_not have_content(&amp;quot;student&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;instructor&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==='''Implement'''===&lt;br /&gt;
 rspec spec/features/users_spec.rb&lt;br /&gt;
&lt;br /&gt;
[[File:Rspec1.png‎  |frame|center|Rspec feature test pass]]&lt;br /&gt;
&lt;br /&gt;
=='''References'''==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95308</id>
		<title>CSC/ECE 517 Spring 2015/oss E1506 SYZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95308"/>
		<updated>2015-03-22T01:44:35Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Delete Uncalled Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;E1506: Refactoring, testing and new features related to “users”&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Overview'''==&lt;br /&gt;
===Code refactoring===&lt;br /&gt;
''Refactoring'' is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior&amp;lt;ref&amp;gt;[http://refactoring.com/ Refactoring]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Refactoring adds to the value of any program that has at least one of the following shortcomings&amp;lt;ref&amp;gt;[http://jexp.de/papers/refactoring/refactoring/node9.html#SECTION00330000000000000000 Benefits of Code Refactoring] Michael Hunger. Oct. 25, 2000&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Programs that are hard to read are hard to modify;&lt;br /&gt;
* Programs that have duplicate logic are hard to modify;&lt;br /&gt;
* Programs that require additional behavior that requires you to change running code are hard to modify;&lt;br /&gt;
* Programs with complex conditional logic are hard to modify.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rspec===&lt;br /&gt;
RSpec is a [http://en.wikipedia.org/wiki/Behavior-driven_development behavior-driven development] (BDD) framework for the [http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby programming language], inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock. The framework can be considered a [http://en.wikipedia.org/wiki/Domain-specific_language domain-specific language] (DSL) and resembles a natural language specification&amp;lt;ref&amp;gt;[http://en.wikipedia.org/wiki/RSpec#cite_note-origin-4g Rspec]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Object-oriented Design Principles===&lt;br /&gt;
Object-oriented programming (OOP) is a programming language model organized around objects rather than &amp;quot;actions&amp;quot; and data rather than logic&amp;lt;ref&amp;gt;[http://searchsoa.techtarget.com/definition/object-oriented-programming Margaret Rouse. ''object-oriented programming (OOP) definition''. Aug 3, 2008]&amp;lt;/ref&amp;gt;. Historically, a program has been viewed as a logical procedure that takes input data, processes it, and produces output data. Though an Object oriented language provides us with highly useful and important programming concepts like '''Inheritance''', '''Polymorphism''', '''Abstraction''' and '''Encapsulation''' which definitely makes the code more efficient, it is equally important to have the knowledge of using them in the code. &lt;br /&gt;
''Object Oriented Design'' Principles are core of OOPS programming&amp;lt;ref&amp;gt;[http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-principles.html#ixzz3Ha8L3cfz Javin Paul. ''Blogspot''. March 3, 2012]&amp;lt;/ref&amp;gt;. It is important to know these design principles, to create clean and modular design. There are many design principles that help us to create clean and efficient code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=='''Project Resources'''==&lt;br /&gt;
* [https://github.com/CSC517-Proj2-E1506/expertiza GitHub Repository]&lt;br /&gt;
* [http://152.46.16.178:3001/ VCL IP] (Log in as user2/password. Go to [http://152.46.16.178:3001/analytic/index VCL analytic page])&lt;br /&gt;
* [https://github.com/expertiza/expertiza/pull/505 GitHub Pull Request Link]&lt;br /&gt;
&lt;br /&gt;
=='''Todo List'''==&lt;br /&gt;
&amp;lt;b&amp;gt;Related files:&amp;lt;/b&amp;gt; users_controller.rb, participants_controller.rb, user.rb, users/show.html.erb&lt;br /&gt;
*  Find the un-called methods if any and delete them. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*  Change the Rails 2 syntax to Rails 4 style.&lt;br /&gt;
*  Refactor users_controller.rb&lt;br /&gt;
** Change the white space for the second harf of this file, starts at “def edit”. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Separate the “paginate_list” method into two methods. The search method should be in model and the paginating method should be in the controller.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* New feature: delete users&lt;br /&gt;
** A user can be deleted if (s)he has not participated in an assignment. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user is participating in an assignment, the system will ask, “User is participating in k assignments.  Delete as a participant in these assignment(s)?”  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden.&lt;br /&gt;
*** rename (javascript calling update method in users_controller.rb) &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*** different users have different delete methods.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Write tests (with Rspec) for this feature.&amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* Testing feature: search for users&lt;br /&gt;
** In rails 4 branch, admins can search for the users with 1) users’ login names 2) users’ last or first names and 3) users’ emails. Please write tests (with Rspec) for this feature &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Delete Uncalled Methods'''==&lt;br /&gt;
The primary way we find unused method is right-click on each method's name, then choose &amp;quot;Find Usage&amp;quot;, as the following picture shows:&lt;br /&gt;
[[File:FindUsages.PNG]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then the finding results will be displayed in the bottom, as the following picture shows:&lt;br /&gt;
[[File:FindResult.PNG]]&lt;br /&gt;
&lt;br /&gt;
=='''Change Rails 2 syntax to Rails 4'''==&lt;br /&gt;
&amp;lt;b&amp;gt;'''with_scope'''&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Refactor users_controller.rb'''==&lt;br /&gt;
&lt;br /&gt;
=='''New feature: delete users'''==&lt;br /&gt;
&lt;br /&gt;
===='''Design'''====&lt;br /&gt;
&lt;br /&gt;
At the very beginning, we decide to use &amp;quot;Cascading Delete&amp;quot; to delete users. Because there are many relationship between different users. They can be reviewer, reviewee, teaching assistant, and so on.If we have to delete an user, we have to not only delete the record in ''user'' table, but also other related tables.&lt;br /&gt;
&lt;br /&gt;
So, we divide all users into two set, one is '''new users''' without any relationship, the other is the '''old user''' with some relationships. And we find that it is quite easy to achieve the functionality of deleting new users. When deleting old users, we find some problems. Because old users may be a reviewer before and score some assignments. If we delete some old users, the assignments' review scores will be a mess.&lt;br /&gt;
&lt;br /&gt;
After discussing with professor, we decide to deprecate&amp;quot;Cascading Delete&amp;quot;. And we use below algorithm to handle user deletion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS0.png‎  |frame|center|Confirm box flow diagram]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* A user can be deleted if (s)he has not participated in an assignment;&lt;br /&gt;
* If the user is participating in an assignment, the system will ask, “User is participating in k assignments. Delete as a participant in these assignment(s)?”;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS1.png‎  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS2.png‎  |frame|center|Rename confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Rename (javascript calling update method in users_controller.rb);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS3.png‎  |frame|center|Rename success 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS4.png‎  |frame|center|Cannot delete]]&lt;br /&gt;
&lt;br /&gt;
===='''Implementation'''====&lt;br /&gt;
&lt;br /&gt;
We add a '''userDeleteConfirmBox.js''' file to implement this unique confirm box algorithm.&lt;br /&gt;
&lt;br /&gt;
* First, we overwrite the Rails default confirm function.&lt;br /&gt;
 $.rails.allowAction = function(link) {&lt;br /&gt;
   console.log(link.attr('data-relationship'))&lt;br /&gt;
   console.log(link.attr('data-username'))&lt;br /&gt;
   if ((!link.attr('data-confirm')) || (link.attr('data-relationship') &amp;amp;&amp;amp; link.attr('data-relationship') == 'false')) {&lt;br /&gt;
    return true;&lt;br /&gt;
   }&lt;br /&gt;
   $.rails.showConfirmDialog(link);&lt;br /&gt;
   return false;&lt;br /&gt;
 };&lt;br /&gt;
 $.rails.confirmed = function(link) {&lt;br /&gt;
   link.removeAttr('data-confirm');&lt;br /&gt;
   return link.trigger('click.rails');&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* Then, we write code to achieve customed confirm box using our own algorithm.&lt;br /&gt;
 $.rails.showConfirmDialog = function(link) {&lt;br /&gt;
  var message = link.attr('data-confirm');&lt;br /&gt;
  //confirmation box style&lt;br /&gt;
  $(function() {&lt;br /&gt;
    $(html1).modal();&lt;br /&gt;
    $(&amp;quot;#dialog-confirm1&amp;quot;).dialog({&lt;br /&gt;
      width: 340,&lt;br /&gt;
      buttons: {&lt;br /&gt;
        &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          location.reload();&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;Yes&amp;quot;: function() {&lt;br /&gt;
          //return $.rails.confirmed(link);&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          $(html2).modal();&lt;br /&gt;
          $(&amp;quot;#dialog-confirm2&amp;quot;).dialog({&lt;br /&gt;
            width: 340,&lt;br /&gt;
            buttons: {&lt;br /&gt;
              &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
                $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;Yes&amp;quot;: function() {                 &lt;br /&gt;
                    $('#rename').click() &lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html3).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm3&amp;quot;).dialog({&lt;br /&gt;
                    width: 340,&lt;br /&gt;
                  });&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;No, delete any way!&amp;quot;: function() {&lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html4).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm4&amp;quot;).dialog({&lt;br /&gt;
                      width: 340,&lt;br /&gt;
                      buttons: {&lt;br /&gt;
                        &amp;quot;Close&amp;quot;: function() {&lt;br /&gt;
                          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                          location.reload();&lt;br /&gt;
                        }&lt;br /&gt;
                      }&lt;br /&gt;
                  });&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
           });&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     });&lt;br /&gt;
  });&lt;br /&gt;
  return $('#dialog-confirm .confirm').on('click', function() {&lt;br /&gt;
    return $.rails.confirmed(link);&lt;br /&gt;
  });&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* After that, we all the if condition in '''/users/show.html.erb''' file. So when deleting the old users, Expertiza uses the functionality and customed confirm box we define; when deleting the new users, Expertiza will use the default confirm box.&lt;br /&gt;
  &amp;lt;% if @assignment_participant_num != 0 and (!@maps.nil? or @maps.length != 0)%&amp;gt; &lt;br /&gt;
      &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User is participating in #{@assignment_participant_num} assignments.&amp;lt;br/&amp;gt;Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'true', :username =&amp;gt; @user.name}, :method =&amp;gt; :delete, remote: true%&amp;gt;   &lt;br /&gt;
  &amp;lt;% else %&amp;gt;&lt;br /&gt;
       &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User joins in #{@assignment_participant_num} assignment(s), but without participates in&lt;br /&gt;
 any assignments. Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'false'}, :method =&amp;gt; :delete, remote: true%&amp;gt;&lt;br /&gt;
   &amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Testing feature: search for users'''==&lt;br /&gt;
&lt;br /&gt;
==='''Design'''===&lt;br /&gt;
&lt;br /&gt;
We write some features test to test &amp;quot;search for users&amp;quot; functionality.&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users bylogin names&lt;br /&gt;
 feature 'Method 1: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by login name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'student'&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Student, Perfect&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;pstudent@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by first name or last name&lt;br /&gt;
 feature 'Method2: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by last or first name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'Bob'&lt;br /&gt;
    find('#search_by').select 'Full name'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by email&lt;br /&gt;
 feature 'Method3: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by email' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'bdole@dev.null'&lt;br /&gt;
    find('#search_by').select 'Email'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor deletes new users&lt;br /&gt;
 feature 'Instructor delete a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'which has no relationship' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    #in order to show whole user list&lt;br /&gt;
    fill_in 'letter', with: ''&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    click_link 'student'&lt;br /&gt;
    click_link 'Delete'&lt;br /&gt;
    expect(page).to_not have_content(&amp;quot;student&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;instructor&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==='''Implement'''===&lt;br /&gt;
 rspec spec/features/users_spec.rb&lt;br /&gt;
&lt;br /&gt;
[[File:Rspec1.png‎  |frame|center|Rspec feature test pass]]&lt;br /&gt;
&lt;br /&gt;
=='''References'''==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:FindResult.PNG&amp;diff=95307</id>
		<title>File:FindResult.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:FindResult.PNG&amp;diff=95307"/>
		<updated>2015-03-22T01:43:27Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: uploaded a new version of &amp;amp;quot;File:FindResult.PNG&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95306</id>
		<title>CSC/ECE 517 Spring 2015/oss E1506 SYZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95306"/>
		<updated>2015-03-22T01:42:35Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Delete Uncalled Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;E1506: Refactoring, testing and new features related to “users”&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Overview'''==&lt;br /&gt;
===Code refactoring===&lt;br /&gt;
''Refactoring'' is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior&amp;lt;ref&amp;gt;[http://refactoring.com/ Refactoring]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Refactoring adds to the value of any program that has at least one of the following shortcomings&amp;lt;ref&amp;gt;[http://jexp.de/papers/refactoring/refactoring/node9.html#SECTION00330000000000000000 Benefits of Code Refactoring] Michael Hunger. Oct. 25, 2000&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Programs that are hard to read are hard to modify;&lt;br /&gt;
* Programs that have duplicate logic are hard to modify;&lt;br /&gt;
* Programs that require additional behavior that requires you to change running code are hard to modify;&lt;br /&gt;
* Programs with complex conditional logic are hard to modify.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rspec===&lt;br /&gt;
RSpec is a [http://en.wikipedia.org/wiki/Behavior-driven_development behavior-driven development] (BDD) framework for the [http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby programming language], inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock. The framework can be considered a [http://en.wikipedia.org/wiki/Domain-specific_language domain-specific language] (DSL) and resembles a natural language specification&amp;lt;ref&amp;gt;[http://en.wikipedia.org/wiki/RSpec#cite_note-origin-4g Rspec]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Object-oriented Design Principles===&lt;br /&gt;
Object-oriented programming (OOP) is a programming language model organized around objects rather than &amp;quot;actions&amp;quot; and data rather than logic&amp;lt;ref&amp;gt;[http://searchsoa.techtarget.com/definition/object-oriented-programming Margaret Rouse. ''object-oriented programming (OOP) definition''. Aug 3, 2008]&amp;lt;/ref&amp;gt;. Historically, a program has been viewed as a logical procedure that takes input data, processes it, and produces output data. Though an Object oriented language provides us with highly useful and important programming concepts like '''Inheritance''', '''Polymorphism''', '''Abstraction''' and '''Encapsulation''' which definitely makes the code more efficient, it is equally important to have the knowledge of using them in the code. &lt;br /&gt;
''Object Oriented Design'' Principles are core of OOPS programming&amp;lt;ref&amp;gt;[http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-principles.html#ixzz3Ha8L3cfz Javin Paul. ''Blogspot''. March 3, 2012]&amp;lt;/ref&amp;gt;. It is important to know these design principles, to create clean and modular design. There are many design principles that help us to create clean and efficient code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=='''Project Resources'''==&lt;br /&gt;
* [https://github.com/CSC517-Proj2-E1506/expertiza GitHub Repository]&lt;br /&gt;
* [http://152.46.16.178:3001/ VCL IP] (Log in as user2/password. Go to [http://152.46.16.178:3001/analytic/index VCL analytic page])&lt;br /&gt;
* [https://github.com/expertiza/expertiza/pull/505 GitHub Pull Request Link]&lt;br /&gt;
&lt;br /&gt;
=='''Todo List'''==&lt;br /&gt;
&amp;lt;b&amp;gt;Related files:&amp;lt;/b&amp;gt; users_controller.rb, participants_controller.rb, user.rb, users/show.html.erb&lt;br /&gt;
*  Find the un-called methods if any and delete them. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*  Change the Rails 2 syntax to Rails 4 style.&lt;br /&gt;
*  Refactor users_controller.rb&lt;br /&gt;
** Change the white space for the second harf of this file, starts at “def edit”. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Separate the “paginate_list” method into two methods. The search method should be in model and the paginating method should be in the controller.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* New feature: delete users&lt;br /&gt;
** A user can be deleted if (s)he has not participated in an assignment. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user is participating in an assignment, the system will ask, “User is participating in k assignments.  Delete as a participant in these assignment(s)?”  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden.&lt;br /&gt;
*** rename (javascript calling update method in users_controller.rb) &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*** different users have different delete methods.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Write tests (with Rspec) for this feature.&amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* Testing feature: search for users&lt;br /&gt;
** In rails 4 branch, admins can search for the users with 1) users’ login names 2) users’ last or first names and 3) users’ emails. Please write tests (with Rspec) for this feature &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Delete Uncalled Methods'''==&lt;br /&gt;
The primary way we find unused method is right-click on each method's name, then choose &amp;quot;Find Usage&amp;quot;, as the following picture shows:&lt;br /&gt;
[[File:FindUsages.PNG]]&lt;br /&gt;
&lt;br /&gt;
Then the finding results will be displayed in the bottom, as the following picture shows:&lt;br /&gt;
[[File:FindResult.PNG]]&lt;br /&gt;
&lt;br /&gt;
=='''Change Rails 2 syntax to Rails 4'''==&lt;br /&gt;
&amp;lt;b&amp;gt;'''with_scope'''&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Refactor users_controller.rb'''==&lt;br /&gt;
&lt;br /&gt;
=='''New feature: delete users'''==&lt;br /&gt;
&lt;br /&gt;
===='''Design'''====&lt;br /&gt;
&lt;br /&gt;
At the very beginning, we decide to use &amp;quot;Cascading Delete&amp;quot; to delete users. Because there are many relationship between different users. They can be reviewer, reviewee, teaching assistant, and so on.If we have to delete an user, we have to not only delete the record in ''user'' table, but also other related tables.&lt;br /&gt;
&lt;br /&gt;
So, we divide all users into two set, one is '''new users''' without any relationship, the other is the '''old user''' with some relationships. And we find that it is quite easy to achieve the functionality of deleting new users. When deleting old users, we find some problems. Because old users may be a reviewer before and score some assignments. If we delete some old users, the assignments' review scores will be a mess.&lt;br /&gt;
&lt;br /&gt;
After discussing with professor, we decide to deprecate&amp;quot;Cascading Delete&amp;quot;. And we use below algorithm to handle user deletion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS0.png‎  |frame|center|Confirm box flow diagram]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* A user can be deleted if (s)he has not participated in an assignment;&lt;br /&gt;
* If the user is participating in an assignment, the system will ask, “User is participating in k assignments. Delete as a participant in these assignment(s)?”;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS1.png‎  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS2.png‎  |frame|center|Rename confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Rename (javascript calling update method in users_controller.rb);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS3.png‎  |frame|center|Rename success 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS4.png‎  |frame|center|Cannot delete]]&lt;br /&gt;
&lt;br /&gt;
===='''Implementation'''====&lt;br /&gt;
&lt;br /&gt;
We add a '''userDeleteConfirmBox.js''' file to implement this unique confirm box algorithm.&lt;br /&gt;
&lt;br /&gt;
* First, we overwrite the Rails default confirm function.&lt;br /&gt;
 $.rails.allowAction = function(link) {&lt;br /&gt;
   console.log(link.attr('data-relationship'))&lt;br /&gt;
   console.log(link.attr('data-username'))&lt;br /&gt;
   if ((!link.attr('data-confirm')) || (link.attr('data-relationship') &amp;amp;&amp;amp; link.attr('data-relationship') == 'false')) {&lt;br /&gt;
    return true;&lt;br /&gt;
   }&lt;br /&gt;
   $.rails.showConfirmDialog(link);&lt;br /&gt;
   return false;&lt;br /&gt;
 };&lt;br /&gt;
 $.rails.confirmed = function(link) {&lt;br /&gt;
   link.removeAttr('data-confirm');&lt;br /&gt;
   return link.trigger('click.rails');&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* Then, we write code to achieve customed confirm box using our own algorithm.&lt;br /&gt;
 $.rails.showConfirmDialog = function(link) {&lt;br /&gt;
  var message = link.attr('data-confirm');&lt;br /&gt;
  //confirmation box style&lt;br /&gt;
  $(function() {&lt;br /&gt;
    $(html1).modal();&lt;br /&gt;
    $(&amp;quot;#dialog-confirm1&amp;quot;).dialog({&lt;br /&gt;
      width: 340,&lt;br /&gt;
      buttons: {&lt;br /&gt;
        &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          location.reload();&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;Yes&amp;quot;: function() {&lt;br /&gt;
          //return $.rails.confirmed(link);&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          $(html2).modal();&lt;br /&gt;
          $(&amp;quot;#dialog-confirm2&amp;quot;).dialog({&lt;br /&gt;
            width: 340,&lt;br /&gt;
            buttons: {&lt;br /&gt;
              &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
                $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;Yes&amp;quot;: function() {                 &lt;br /&gt;
                    $('#rename').click() &lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html3).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm3&amp;quot;).dialog({&lt;br /&gt;
                    width: 340,&lt;br /&gt;
                  });&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;No, delete any way!&amp;quot;: function() {&lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html4).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm4&amp;quot;).dialog({&lt;br /&gt;
                      width: 340,&lt;br /&gt;
                      buttons: {&lt;br /&gt;
                        &amp;quot;Close&amp;quot;: function() {&lt;br /&gt;
                          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                          location.reload();&lt;br /&gt;
                        }&lt;br /&gt;
                      }&lt;br /&gt;
                  });&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
           });&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     });&lt;br /&gt;
  });&lt;br /&gt;
  return $('#dialog-confirm .confirm').on('click', function() {&lt;br /&gt;
    return $.rails.confirmed(link);&lt;br /&gt;
  });&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* After that, we all the if condition in '''/users/show.html.erb''' file. So when deleting the old users, Expertiza uses the functionality and customed confirm box we define; when deleting the new users, Expertiza will use the default confirm box.&lt;br /&gt;
  &amp;lt;% if @assignment_participant_num != 0 and (!@maps.nil? or @maps.length != 0)%&amp;gt; &lt;br /&gt;
      &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User is participating in #{@assignment_participant_num} assignments.&amp;lt;br/&amp;gt;Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'true', :username =&amp;gt; @user.name}, :method =&amp;gt; :delete, remote: true%&amp;gt;   &lt;br /&gt;
  &amp;lt;% else %&amp;gt;&lt;br /&gt;
       &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User joins in #{@assignment_participant_num} assignment(s), but without participates in&lt;br /&gt;
 any assignments. Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'false'}, :method =&amp;gt; :delete, remote: true%&amp;gt;&lt;br /&gt;
   &amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Testing feature: search for users'''==&lt;br /&gt;
&lt;br /&gt;
==='''Design'''===&lt;br /&gt;
&lt;br /&gt;
We write some features test to test &amp;quot;search for users&amp;quot; functionality.&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users bylogin names&lt;br /&gt;
 feature 'Method 1: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by login name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'student'&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Student, Perfect&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;pstudent@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by first name or last name&lt;br /&gt;
 feature 'Method2: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by last or first name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'Bob'&lt;br /&gt;
    find('#search_by').select 'Full name'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by email&lt;br /&gt;
 feature 'Method3: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by email' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'bdole@dev.null'&lt;br /&gt;
    find('#search_by').select 'Email'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor deletes new users&lt;br /&gt;
 feature 'Instructor delete a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'which has no relationship' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    #in order to show whole user list&lt;br /&gt;
    fill_in 'letter', with: ''&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    click_link 'student'&lt;br /&gt;
    click_link 'Delete'&lt;br /&gt;
    expect(page).to_not have_content(&amp;quot;student&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;instructor&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==='''Implement'''===&lt;br /&gt;
 rspec spec/features/users_spec.rb&lt;br /&gt;
&lt;br /&gt;
[[File:Rspec1.png‎  |frame|center|Rspec feature test pass]]&lt;br /&gt;
&lt;br /&gt;
=='''References'''==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:FindResult.PNG&amp;diff=95305</id>
		<title>File:FindResult.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:FindResult.PNG&amp;diff=95305"/>
		<updated>2015-03-22T01:42:04Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95304</id>
		<title>CSC/ECE 517 Spring 2015/oss E1506 SYZ</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1506_SYZ&amp;diff=95304"/>
		<updated>2015-03-22T01:41:35Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Delete Uncalled Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;E1506: Refactoring, testing and new features related to “users”&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Overview'''==&lt;br /&gt;
===Code refactoring===&lt;br /&gt;
''Refactoring'' is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior&amp;lt;ref&amp;gt;[http://refactoring.com/ Refactoring]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Refactoring adds to the value of any program that has at least one of the following shortcomings&amp;lt;ref&amp;gt;[http://jexp.de/papers/refactoring/refactoring/node9.html#SECTION00330000000000000000 Benefits of Code Refactoring] Michael Hunger. Oct. 25, 2000&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Programs that are hard to read are hard to modify;&lt;br /&gt;
* Programs that have duplicate logic are hard to modify;&lt;br /&gt;
* Programs that require additional behavior that requires you to change running code are hard to modify;&lt;br /&gt;
* Programs with complex conditional logic are hard to modify.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rspec===&lt;br /&gt;
RSpec is a [http://en.wikipedia.org/wiki/Behavior-driven_development behavior-driven development] (BDD) framework for the [http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby programming language], inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock. The framework can be considered a [http://en.wikipedia.org/wiki/Domain-specific_language domain-specific language] (DSL) and resembles a natural language specification&amp;lt;ref&amp;gt;[http://en.wikipedia.org/wiki/RSpec#cite_note-origin-4g Rspec]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Object-oriented Design Principles===&lt;br /&gt;
Object-oriented programming (OOP) is a programming language model organized around objects rather than &amp;quot;actions&amp;quot; and data rather than logic&amp;lt;ref&amp;gt;[http://searchsoa.techtarget.com/definition/object-oriented-programming Margaret Rouse. ''object-oriented programming (OOP) definition''. Aug 3, 2008]&amp;lt;/ref&amp;gt;. Historically, a program has been viewed as a logical procedure that takes input data, processes it, and produces output data. Though an Object oriented language provides us with highly useful and important programming concepts like '''Inheritance''', '''Polymorphism''', '''Abstraction''' and '''Encapsulation''' which definitely makes the code more efficient, it is equally important to have the knowledge of using them in the code. &lt;br /&gt;
''Object Oriented Design'' Principles are core of OOPS programming&amp;lt;ref&amp;gt;[http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-principles.html#ixzz3Ha8L3cfz Javin Paul. ''Blogspot''. March 3, 2012]&amp;lt;/ref&amp;gt;. It is important to know these design principles, to create clean and modular design. There are many design principles that help us to create clean and efficient code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=='''Project Resources'''==&lt;br /&gt;
* [https://github.com/CSC517-Proj2-E1506/expertiza GitHub Repository]&lt;br /&gt;
* [http://152.46.16.178:3001/ VCL IP] (Log in as user2/password. Go to [http://152.46.16.178:3001/analytic/index VCL analytic page])&lt;br /&gt;
* [https://github.com/expertiza/expertiza/pull/505 GitHub Pull Request Link]&lt;br /&gt;
&lt;br /&gt;
=='''Todo List'''==&lt;br /&gt;
&amp;lt;b&amp;gt;Related files:&amp;lt;/b&amp;gt; users_controller.rb, participants_controller.rb, user.rb, users/show.html.erb&lt;br /&gt;
*  Find the un-called methods if any and delete them. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*  Change the Rails 2 syntax to Rails 4 style.&lt;br /&gt;
*  Refactor users_controller.rb&lt;br /&gt;
** Change the white space for the second harf of this file, starts at “def edit”. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Separate the “paginate_list” method into two methods. The search method should be in model and the paginating method should be in the controller.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* New feature: delete users&lt;br /&gt;
** A user can be deleted if (s)he has not participated in an assignment. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user is participating in an assignment, the system will ask, “User is participating in k assignments.  Delete as a participant in these assignment(s)?”  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden.&lt;br /&gt;
*** rename (javascript calling update method in users_controller.rb) &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
*** different users have different delete methods.  &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted. &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
** Write tests (with Rspec) for this feature.&amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
* Testing feature: search for users&lt;br /&gt;
** In rails 4 branch, admins can search for the users with 1) users’ login names 2) users’ last or first names and 3) users’ emails. Please write tests (with Rspec) for this feature &amp;lt;b&amp;gt;[done]&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Delete Uncalled Methods'''==&lt;br /&gt;
The primary way we find unused method is right-click on each method's name, then choose &amp;quot;Find Usage&amp;quot;, as the following picture shows:&lt;br /&gt;
[[File:FindUsages.PNG]]&lt;br /&gt;
Then the finding results will be displayed in the bottom, as the following picture shows:&lt;br /&gt;
[[File:FindResult.PNG]]&lt;br /&gt;
&lt;br /&gt;
=='''Change Rails 2 syntax to Rails 4'''==&lt;br /&gt;
&amp;lt;b&amp;gt;'''with_scope'''&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Refactor users_controller.rb'''==&lt;br /&gt;
&lt;br /&gt;
=='''New feature: delete users'''==&lt;br /&gt;
&lt;br /&gt;
===='''Design'''====&lt;br /&gt;
&lt;br /&gt;
At the very beginning, we decide to use &amp;quot;Cascading Delete&amp;quot; to delete users. Because there are many relationship between different users. They can be reviewer, reviewee, teaching assistant, and so on.If we have to delete an user, we have to not only delete the record in ''user'' table, but also other related tables.&lt;br /&gt;
&lt;br /&gt;
So, we divide all users into two set, one is '''new users''' without any relationship, the other is the '''old user''' with some relationships. And we find that it is quite easy to achieve the functionality of deleting new users. When deleting old users, we find some problems. Because old users may be a reviewer before and score some assignments. If we delete some old users, the assignments' review scores will be a mess.&lt;br /&gt;
&lt;br /&gt;
After discussing with professor, we decide to deprecate&amp;quot;Cascading Delete&amp;quot;. And we use below algorithm to handle user deletion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS0.png‎  |frame|center|Confirm box flow diagram]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* A user can be deleted if (s)he has not participated in an assignment;&lt;br /&gt;
* If the user is participating in an assignment, the system will ask, “User is participating in k assignments. Delete as a participant in these assignment(s)?”;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS1.png‎  |frame|center|Delete confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the user has submitted or reviewed in any of these assignments, the system will say the user cannot be deleted, but offer to rename the user account to &amp;lt;current_account_name&amp;gt;_hidden;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS2.png‎  |frame|center|Rename confirm box]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Rename (javascript calling update method in users_controller.rb);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS3.png‎  |frame|center|Rename success 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* If the person trying to delete does not want to rename the account, the system will just say that the user can’t be deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:OSS4.png‎  |frame|center|Cannot delete]]&lt;br /&gt;
&lt;br /&gt;
===='''Implementation'''====&lt;br /&gt;
&lt;br /&gt;
We add a '''userDeleteConfirmBox.js''' file to implement this unique confirm box algorithm.&lt;br /&gt;
&lt;br /&gt;
* First, we overwrite the Rails default confirm function.&lt;br /&gt;
 $.rails.allowAction = function(link) {&lt;br /&gt;
   console.log(link.attr('data-relationship'))&lt;br /&gt;
   console.log(link.attr('data-username'))&lt;br /&gt;
   if ((!link.attr('data-confirm')) || (link.attr('data-relationship') &amp;amp;&amp;amp; link.attr('data-relationship') == 'false')) {&lt;br /&gt;
    return true;&lt;br /&gt;
   }&lt;br /&gt;
   $.rails.showConfirmDialog(link);&lt;br /&gt;
   return false;&lt;br /&gt;
 };&lt;br /&gt;
 $.rails.confirmed = function(link) {&lt;br /&gt;
   link.removeAttr('data-confirm');&lt;br /&gt;
   return link.trigger('click.rails');&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* Then, we write code to achieve customed confirm box using our own algorithm.&lt;br /&gt;
 $.rails.showConfirmDialog = function(link) {&lt;br /&gt;
  var message = link.attr('data-confirm');&lt;br /&gt;
  //confirmation box style&lt;br /&gt;
  $(function() {&lt;br /&gt;
    $(html1).modal();&lt;br /&gt;
    $(&amp;quot;#dialog-confirm1&amp;quot;).dialog({&lt;br /&gt;
      width: 340,&lt;br /&gt;
      buttons: {&lt;br /&gt;
        &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          location.reload();&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;Yes&amp;quot;: function() {&lt;br /&gt;
          //return $.rails.confirmed(link);&lt;br /&gt;
          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
          $(html2).modal();&lt;br /&gt;
          $(&amp;quot;#dialog-confirm2&amp;quot;).dialog({&lt;br /&gt;
            width: 340,&lt;br /&gt;
            buttons: {&lt;br /&gt;
              &amp;quot;Cancel&amp;quot;: function() {&lt;br /&gt;
                $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;Yes&amp;quot;: function() {                 &lt;br /&gt;
                    $('#rename').click() &lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html3).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm3&amp;quot;).dialog({&lt;br /&gt;
                    width: 340,&lt;br /&gt;
                  });&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;No, delete any way!&amp;quot;: function() {&lt;br /&gt;
                  $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                  $(html4).modal();&lt;br /&gt;
                  $(&amp;quot;#dialog-confirm4&amp;quot;).dialog({&lt;br /&gt;
                      width: 340,&lt;br /&gt;
                      buttons: {&lt;br /&gt;
                        &amp;quot;Close&amp;quot;: function() {&lt;br /&gt;
                          $( this ).dialog( &amp;quot;close&amp;quot; );&lt;br /&gt;
                          location.reload();&lt;br /&gt;
                        }&lt;br /&gt;
                      }&lt;br /&gt;
                  });&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
           });&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     });&lt;br /&gt;
  });&lt;br /&gt;
  return $('#dialog-confirm .confirm').on('click', function() {&lt;br /&gt;
    return $.rails.confirmed(link);&lt;br /&gt;
  });&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
* After that, we all the if condition in '''/users/show.html.erb''' file. So when deleting the old users, Expertiza uses the functionality and customed confirm box we define; when deleting the new users, Expertiza will use the default confirm box.&lt;br /&gt;
  &amp;lt;% if @assignment_participant_num != 0 and (!@maps.nil? or @maps.length != 0)%&amp;gt; &lt;br /&gt;
      &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User is participating in #{@assignment_participant_num} assignments.&amp;lt;br/&amp;gt;Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'true', :username =&amp;gt; @user.name}, :method =&amp;gt; :delete, remote: true%&amp;gt;   &lt;br /&gt;
  &amp;lt;% else %&amp;gt;&lt;br /&gt;
       &amp;lt;%= link_to 'Delete', {:action =&amp;gt; 'destroy', :id =&amp;gt; @user}, data:{:confirm =&amp;gt; &amp;quot;User joins in #{@assignment_participant_num} assignment(s), but without participates in&lt;br /&gt;
 any assignments. Delete as a participant in these assignment(s)?&amp;quot;, :relationship =&amp;gt; 'false'}, :method =&amp;gt; :delete, remote: true%&amp;gt;&lt;br /&gt;
   &amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=='''Testing feature: search for users'''==&lt;br /&gt;
&lt;br /&gt;
==='''Design'''===&lt;br /&gt;
&lt;br /&gt;
We write some features test to test &amp;quot;search for users&amp;quot; functionality.&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users bylogin names&lt;br /&gt;
 feature 'Method 1: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by login name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'student'&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Student, Perfect&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;pstudent@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by first name or last name&lt;br /&gt;
 feature 'Method2: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by last or first name' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'Bob'&lt;br /&gt;
    find('#search_by').select 'Full name'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor searches users by email&lt;br /&gt;
 feature 'Method3: Instructor search a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'by email' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    fill_in 'letter', with: 'bdole@dev.null'&lt;br /&gt;
    find('#search_by').select 'Email'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    expect(page).to have_content(&amp;quot;Dole, Bob&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;bdole@dev.null&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* Instructor deletes new users&lt;br /&gt;
 feature 'Instructor delete a user' do&lt;br /&gt;
  before(:all) do&lt;br /&gt;
    instructor.save&lt;br /&gt;
    student.save&lt;br /&gt;
    log_in instructor.name, &amp;quot;password&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  scenario 'which has no relationship' do&lt;br /&gt;
    visit '/users/list'&lt;br /&gt;
    #in order to show whole user list&lt;br /&gt;
    fill_in 'letter', with: ''&lt;br /&gt;
    find('#search_by').select 'Username'&lt;br /&gt;
    click_button 'Search'&lt;br /&gt;
    click_link 'student'&lt;br /&gt;
    click_link 'Delete'&lt;br /&gt;
    expect(page).to_not have_content(&amp;quot;student&amp;quot;)&lt;br /&gt;
    expect(page).to have_content(&amp;quot;instructor&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==='''Implement'''===&lt;br /&gt;
 rspec spec/features/users_spec.rb&lt;br /&gt;
&lt;br /&gt;
[[File:Rspec1.png‎  |frame|center|Rspec feature test pass]]&lt;br /&gt;
&lt;br /&gt;
=='''References'''==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:FindUsages.PNG&amp;diff=95303</id>
		<title>File:FindUsages.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:FindUsages.PNG&amp;diff=95303"/>
		<updated>2015-03-22T01:37:54Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93832</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93832"/>
		<updated>2015-02-16T04:00:47Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Conclusion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
In Rails, the concept of streaming first appeared in [http://weblog.rubyonrails.org/releases/ version 3.1], and is further optimized in Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Examples'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Some basic knowledge about how web pages are rendered can be found [http://friendlybit.com/css/rendering-a-web-page-step-by-step/ here] and also [http://www.pathinteractive.com/blog/2014/07/rendering-a-webpage-with-google-webmaster-tools/ here]. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Since Rail 3.1, [http://api.rubyonrails.org/classes/ActionController/Streaming.html ''::Streaming''] module has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt;Template Streaming, George Ogata https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ''::Streaming'' inverts the regular Rails process of rendering the layout and template. Using ''::Streaming'', Rails will render template first and then layout. It will first run method ''yield'' and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like ''new'' or ''edit'', it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: '':Streaming'' only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;ActionController::Streaming http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won't need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;ActionController::Streaming http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield '':title'' in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module [http://api.rubyonrails.org/classes/ActionController/Live.html ''::Live''] was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ''::Live'' requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will '''keep loading and remain blank''' for 8 seconds, and shows all 8 lines of “This is a response message!” altogether, as with the following image shows:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:nostreaming.gif]]&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ''ActionController::Live''. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ''ActionController::Live''. Now '''data can be streamed to the client immediately whenever write method is called'''. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 8 times.&amp;lt;ref&amp;gt;Is it live? http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt; Like the image shows below:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:streaming.gif]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Server-sent_events Server-sent event (SSE)] is a technology where browser can automatically receive update data from a server via [https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP] connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of [https://en.wikipedia.org/wiki/HTML5 HTML5] by the [https://en.wikipedia.org/wiki/World_Wide_Web_Consortium W3C]. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;Server-sent events https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in [https://en.wikipedia.org/wiki/JSON JSON] format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Conclusion'''=&lt;br /&gt;
The supporting for live streaming has deep impact on Rails. It not only makes Rails more competitive with Node.js, but also opens a gate for Rails to embrace lots of new areas and applications that it does not fits well before. The main advantage of Rails can be summarized as follows:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;Why Rails 4 Live Streaming is a big deal, Hongli Lai http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original [https://en.wikipedia.org/wiki/WEBrick WEBrick] server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;Installing puma on windows, Robert Kranz https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93831</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93831"/>
		<updated>2015-02-16T03:46:40Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Template streaming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
In Rails, the concept of streaming first appeared in [http://weblog.rubyonrails.org/releases/ version 3.1], and is further optimized in Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Examples'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Some basic knowledge about how web pages are rendered can be found [http://friendlybit.com/css/rendering-a-web-page-step-by-step/ here] and also [http://www.pathinteractive.com/blog/2014/07/rendering-a-webpage-with-google-webmaster-tools/ here]. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Since Rail 3.1, [http://api.rubyonrails.org/classes/ActionController/Streaming.html ''::Streaming''] module has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt;Template Streaming, George Ogata https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ''::Streaming'' inverts the regular Rails process of rendering the layout and template. Using ''::Streaming'', Rails will render template first and then layout. It will first run method ''yield'' and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like ''new'' or ''edit'', it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: '':Streaming'' only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;ActionController::Streaming http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won't need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;ActionController::Streaming http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield '':title'' in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module [http://api.rubyonrails.org/classes/ActionController/Live.html ''::Live''] was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ''::Live'' requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will '''keep loading and remain blank''' for 8 seconds, and shows all 8 lines of “This is a response message!” altogether, as with the following image shows:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:nostreaming.gif]]&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ''ActionController::Live''. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ''ActionController::Live''. Now '''data can be streamed to the client immediately whenever write method is called'''. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 8 times.&amp;lt;ref&amp;gt;Is it live? http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt; Like the image shows below:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:streaming.gif]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Server-sent_events Server-sent event (SSE)] is a technology where browser can automatically receive update data from a server via [https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP] connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of [https://en.wikipedia.org/wiki/HTML5 HTML5] by the [https://en.wikipedia.org/wiki/World_Wide_Web_Consortium W3C]. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;Server-sent events https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in [https://en.wikipedia.org/wiki/JSON JSON] format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Conclusion'''=&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;Why Rails 4 Live Streaming is a big deal, Hongli Lai http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original [https://en.wikipedia.org/wiki/WEBrick WEBrick] server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;Installing puma on windows, Robert Kranz https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93820</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93820"/>
		<updated>2015-02-16T03:30:27Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Template streaming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
In Rails, the concept of streaming first appeared in [http://weblog.rubyonrails.org/releases/ version 3.1], and is further optimized in Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Details'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Some basic knowledge about how web pages are rendered can be found [http://friendlybit.com/css/rendering-a-web-page-step-by-step/ here] and [http://www.pathinteractive.com/blog/2014/07/rendering-a-webpage-with-google-webmaster-tools/ here]. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Since Rail 3.1, [http://api.rubyonrails.org/classes/ActionController/Streaming.html ''::Streaming''] module has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt;Template Streaming, George Ogata https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ''::Streaming'' inverts the regular Rails process of rendering the layout and template. Using ''::Streaming'', Rails will render template first and then layout. It will first run method ''yield'' and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like ''new'' or ''edit'', it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: '':Streaming'' only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;ActionController::Streaming http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won't need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;ActionController::Streaming http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield '':title'' in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module [http://api.rubyonrails.org/classes/ActionController/Live.html ''::Live''] was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ''::Live'' requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will '''keep loading and remain blank''' for 8 seconds, and shows all 8 lines of “This is a response message!” altogether, as with the following image shows:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:nostreaming.gif]]&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ''ActionController::Live''. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ''ActionController::Live''. Now '''data can be streamed to the client immediately whenever write method is called'''. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 8 times.&amp;lt;ref&amp;gt;Is it live? http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt; Like the image shows below:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:streaming.gif]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Server-sent_events Server-sent event (SSE)] is a technology where browser can automatically receive update data from a server via [https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP] connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of [https://en.wikipedia.org/wiki/HTML5 HTML5] by the [https://en.wikipedia.org/wiki/World_Wide_Web_Consortium W3C]. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;Server-sent events https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in [https://en.wikipedia.org/wiki/JSON JSON] format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Benefit of live streaming==&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;Why Rails 4 Live Streaming is a big deal, Hongli Lai http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original [https://en.wikipedia.org/wiki/WEBrick WEBrick] server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;Installing puma on windows, Robert Kranz https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93819</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93819"/>
		<updated>2015-02-16T03:26:01Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Template streaming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
In Rails, the concept of streaming first appeared in [http://weblog.rubyonrails.org/releases/ version 3.1], and is further optimized in Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Details'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Some basic knowledge about how web pages are rendered can be found [http://friendlybit.com/css/rendering-a-web-page-step-by-step/ here] and [http://www.pathinteractive.com/blog/2014/07/rendering-a-webpage-with-google-webmaster-tools/ here]. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Since Rail 3.1, [http://api.rubyonrails.org/classes/ActionController/Streaming.html ''::Streaming''] module has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt;Template Streaming, George Ogata https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ''::Streaming'' inverts the regular Rails process of rendering the layout and template. Using ''::Streaming'', Rails will render template first and then layout. It will first run method yield and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like new or edit, it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: '':Streaming'' only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;ActionController::Streaming http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won't need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;ActionController::Streaming http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield '':title'' in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module [http://api.rubyonrails.org/classes/ActionController/Live.html ''::Live''] was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ''::Live'' requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will '''keep loading and remain blank''' for 8 seconds, and shows all 8 lines of “This is a response message!” altogether, as with the following image shows:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:nostreaming.gif]]&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ''ActionController::Live''. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ''ActionController::Live''. Now '''data can be streamed to the client immediately whenever write method is called'''. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 8 times.&amp;lt;ref&amp;gt;Is it live? http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt; Like the image shows below:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:streaming.gif]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Server-sent_events Server-sent event (SSE)] is a technology where browser can automatically receive update data from a server via [https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP] connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of [https://en.wikipedia.org/wiki/HTML5 HTML5] by the [https://en.wikipedia.org/wiki/World_Wide_Web_Consortium W3C]. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;Server-sent events https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in [https://en.wikipedia.org/wiki/JSON JSON] format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Benefit of live streaming==&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;Why Rails 4 Live Streaming is a big deal, Hongli Lai http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original [https://en.wikipedia.org/wiki/WEBrick WEBrick] server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;Installing puma on windows, Robert Kranz https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Nostreaming.gif&amp;diff=93808</id>
		<title>File:Nostreaming.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Nostreaming.gif&amp;diff=93808"/>
		<updated>2015-02-16T03:10:13Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: uploaded a new version of &amp;amp;quot;File:Nostreaming.gif&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;No streaming example.&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Nostreaming.gif&amp;diff=93807</id>
		<title>File:Nostreaming.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Nostreaming.gif&amp;diff=93807"/>
		<updated>2015-02-16T03:06:16Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: uploaded a new version of &amp;amp;quot;File:Nostreaming.gif&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;No streaming example.&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93803</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93803"/>
		<updated>2015-02-16T02:56:12Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Template streaming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
In Rails, the concept of streaming first appeared in [http://weblog.rubyonrails.org/releases/ version 3.1], and is further optimized in Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Details'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Since Rail 3.1, [http://api.rubyonrails.org/classes/ActionController/Streaming.html ''::Streaming''] module has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt; https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ''::Streaming'' inverts the regular Rails process of rendering the layout and template. Using ''::Streaming'', Rails will render template first and then layout. It will first run method yield and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like new or edit, it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: '':Streaming'' only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won't need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield '':title'' in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module [http://api.rubyonrails.org/classes/ActionController/Live.html ''::Live''] was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ''::Live'' requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will '''keep loading and remain blank''' for 8 seconds, and shows all 8 lines of “This is a response message!” altogether, as with the following image shows:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:nostreaming.gif]]&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ''ActionController::Live''. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ''ActionController::Live''. Now '''data can be streamed to the client immediately whenever write method is called'''. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 8 times.&amp;lt;ref&amp;gt;http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt; Like the image shows below:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:streaming.gif]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
Server-sent event (SSE) is a technology where browser can automatically receive update data from a server via HTTP connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of HTML5 by the W3C. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in JSON format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Benefit of live streaming==&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original WEBrick server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93800</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93800"/>
		<updated>2015-02-16T02:54:27Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
In Rails, the concept of streaming first appeared in [http://weblog.rubyonrails.org/releases/ version 3.1], and is further optimized in Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Details'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Since Rail 3.1, [http://api.rubyonrails.org/classes/ActionController/Streaming.html ''::Streaming'' module] has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt; https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ''::Streaming'' inverts the regular Rails process of rendering the layout and template. Using ''::Streaming'', Rails will render template first and then layout. It will first run method yield and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like new or edit, it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: '':Streaming'' only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won’t need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield '':title'' in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module ''::Live'' was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ::Live requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will '''keep loading and remain blank''' for 8 seconds, and shows all 8 lines of “This is a response message!” altogether, as with the following image shows:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:nostreaming.gif]]&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ActionController::Live. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ActionController::Live. Now '''data can be streamed to the client immediately whenever write method is called'''. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 8 times.&amp;lt;ref&amp;gt;http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt; Like the image shows below:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:streaming.gif]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
Server-sent event (SSE) is a technology where browser can automatically receive update data from a server via HTTP connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of HTML5 by the W3C. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in JSON format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Benefit of live streaming==&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original WEBrick server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93795</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93795"/>
		<updated>2015-02-16T02:38:19Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Traditional Response */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
The concept of streaming first appeared in Rails 3.1, and is better further optimized along with the publish of Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Details'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Since Rail 3.1, [http://api.rubyonrails.org/classes/ActionController/Streaming.html/ ''::Streaming'' module] has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt; https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ''::Streaming'' inverts the regular Rails process of rendering the layout and template. Using ''::Streaming'', Rails will render template first and then layout. It will first run method yield and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like new or edit, it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: :Streaming only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won’t need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield :title in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module ''::Live'' was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ::Live requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will '''keep loading and remain blank''' for 8 seconds, and shows all 8 lines of “This is a response message!” altogether, as with the following image shows:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:nostreaming.gif]]&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ActionController::Live. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ActionController::Live. Now '''data can be streamed to the client immediately whenever write method is called'''. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 8 times.&amp;lt;ref&amp;gt;http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt; Like the image shows below:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:streaming.gif]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
Server-sent event (SSE) is a technology where browser can automatically receive update data from a server via HTTP connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of HTML5 by the W3C. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in JSON format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Benefit of live streaming==&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original WEBrick server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93794</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93794"/>
		<updated>2015-02-16T02:37:52Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Live Streaming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
The concept of streaming first appeared in Rails 3.1, and is better further optimized along with the publish of Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Details'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Since Rail 3.1, [http://api.rubyonrails.org/classes/ActionController/Streaming.html/ ''::Streaming'' module] has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt; https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ''::Streaming'' inverts the regular Rails process of rendering the layout and template. Using ''::Streaming'', Rails will render template first and then layout. It will first run method yield and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like new or edit, it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: :Streaming only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won’t need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield :title in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module ''::Live'' was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ::Live requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will '''keep loading and remain blank''' for 8 seconds, and shows all 8 lines of “This is a response message!” altogether, as with the following image shows:&lt;br /&gt;
[[File:nostreaming.gif]]&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ActionController::Live. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ActionController::Live. Now '''data can be streamed to the client immediately whenever write method is called'''. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 8 times.&amp;lt;ref&amp;gt;http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt; Like the image shows below:&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:streaming.gif]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
Server-sent event (SSE) is a technology where browser can automatically receive update data from a server via HTTP connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of HTML5 by the W3C. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in JSON format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Benefit of live streaming==&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original WEBrick server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93793</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93793"/>
		<updated>2015-02-16T02:36:35Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Live Streaming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
The concept of streaming first appeared in Rails 3.1, and is better further optimized along with the publish of Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Details'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Since Rail 3.1, [http://api.rubyonrails.org/classes/ActionController/Streaming.html/ ''::Streaming'' module] has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt; https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ''::Streaming'' inverts the regular Rails process of rendering the layout and template. Using ''::Streaming'', Rails will render template first and then layout. It will first run method yield and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like new or edit, it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: :Streaming only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won’t need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield :title in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module ''::Live'' was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ::Live requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will '''keep loading and remain blank''' for 8 seconds, and shows all 8 lines of “This is a response message!” altogether, as with the following image shows:&lt;br /&gt;
[[File:nostreaming.gif]]&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ActionController::Live. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ActionController::Live. Now '''data can be streamed to the client immediately whenever write method is called'''. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 8 times.&amp;lt;ref&amp;gt;http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt;Like the image shows below:&lt;br /&gt;
[[File:streaming.gif]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
Server-sent event (SSE) is a technology where browser can automatically receive update data from a server via HTTP connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of HTML5 by the W3C. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in JSON format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Benefit of live streaming==&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original WEBrick server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93791</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93791"/>
		<updated>2015-02-16T02:34:46Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Traditional Response */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
The concept of streaming first appeared in Rails 3.1, and is better further optimized along with the publish of Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Details'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Since Rail 3.1, ::Streaming module has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt; https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ::Streaming inverts the regular Rails process of rendering the layout and template. Using ::Streaming, Rails will render template first and then layout. It will first run method yield and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like new or edit, it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: :Streaming only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won’t need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield :title in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module ::Live was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ::Live requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   8.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will '''keep loading and remain blank''' for 8 seconds, and shows all 8 lines of “This is a response message!” altogether, as with the following image shows:&lt;br /&gt;
[[File:nostreaming.gif]]&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ActionController::Live. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   10.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ActionController::Live. Now data can be streamed to the client each time when write method is called. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 10 times.&amp;lt;ref&amp;gt;http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
Server-sent event (SSE) is a technology where browser can automatically receive update data from a server via HTTP connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of HTML5 by the W3C. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in JSON format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Benefit of live streaming==&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original WEBrick server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Streaming.gif&amp;diff=93790</id>
		<title>File:Streaming.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Streaming.gif&amp;diff=93790"/>
		<updated>2015-02-16T02:33:01Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: Streaming example.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Streaming example.&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Nostreaming.gif&amp;diff=93789</id>
		<title>File:Nostreaming.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Nostreaming.gif&amp;diff=93789"/>
		<updated>2015-02-16T02:32:09Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: No streaming example.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;No streaming example.&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93786</id>
		<title>CSC/ECE 517 Spring 2015/ch1a 12 LS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/ch1a_12_LS&amp;diff=93786"/>
		<updated>2015-02-16T01:47:06Z</updated>

		<summary type="html">&lt;p&gt;Ylu31: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Live Streaming&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Introduction'''=&lt;br /&gt;
The purpose of live streaming is to send data over the Internet in real-time. This requires a data source, a data encoder, a media publisher and a proper network.&lt;br /&gt;
&lt;br /&gt;
The concept of streaming first appeared in Rails 3.1, and is better further optimized along with the publish of Rails 4. Now Rails 4 supports live streaming, which uses handling I/O object and can send data from server to client in real-time. &lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
='''Details'''=&lt;br /&gt;
==Template streaming==&lt;br /&gt;
Since Rail 3.1, ::Streaming module has been added to ActionController. For example, the loading progress in a traditional Rails client-side may look like this&amp;lt;ref&amp;gt; https://github.com/oggy/template_streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:slow-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 1 progress without streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
This is because that layouts are rendered before the content, thus causing control flow to be altered to render the page in the order that the client needs (layout first).But for some resources which are static, if they could be loaded while waiting for the server response, a lot of time can be saved. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The module ::Streaming inverts the regular Rails process of rendering the layout and template. Using ::Streaming, Rails will render template first and then layout. It will first run method yield and load up the template, and then renders the assets and layouts. In this way, the progress with streaming looks like this:&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt; &lt;br /&gt;
[[File:fast-profile.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;Figure 2 progress with streaming&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===When to use streaming===&lt;br /&gt;
For actions like new or edit, it may not be that necessary to use streaming. But for expensive actions like database query and generation of large amount of data, streaming can be extremely important and effective. Take the following action as an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since most of the queries here are executing in the controller, it might take a while before them to finish, thus causing the front end (user) to wait for long. We can solve this problem and enhance user experience, the above code can be rewrite as follows,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def storyboard&lt;br /&gt;
  # Allow lazy execution of the queries&lt;br /&gt;
  @stories = Story.all&lt;br /&gt;
  @developers = Page.all&lt;br /&gt;
  @comments = Comment.all&lt;br /&gt;
  render :stream =&amp;gt; true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(Note: :Streaming only works with templates. It doesn’t work with :json or :xml)&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tweaking views===&lt;br /&gt;
When using streaming, instance variables that are set in the template and are used in the layout won’t need some tweak to work well. This is done by using content_for, provide and yield.&lt;br /&gt;
Here’s a simple example where the layout expects the template to tell which title to use&amp;lt;ref&amp;gt;http://apidock.com/rails/ActionController/Streaming&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;%= yield :title %&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;&amp;lt;%= yield %&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of yield, we can also use content_for to specify the title: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, if content_for is called several times, the final result would have all calls concatenated.&lt;br /&gt;
For instance, if we have the following template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The final result would be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that, if you have yield :title in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this reason Rails 3.1 introduces a new helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
For instance, the template above using provide would be: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%= provide :title, &amp;quot;Main&amp;quot; %&amp;gt;&lt;br /&gt;
Hello&lt;br /&gt;
&amp;lt;%= content_for :title, &amp;quot; page&amp;quot; %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Giving:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Main&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Live Streaming==&lt;br /&gt;
The module ::Live was then added to ActionController at Rail 4. The difference between Streaming and Live is that Streaming is implicitly included whenever you create a new controller class, while ::Live requires explicit include.&lt;br /&gt;
&lt;br /&gt;
===Traditional Response===&lt;br /&gt;
In this type of communication between server and client, data will be buffered until all render works are finished, and everything will be sent to the client at the same time. And the stream object behaves just like an IO object. Here’s the sample code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   10.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a response message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run the code above, the web page will remain blank for 10 seconds, and shows all 10 lines of “This is a response message!” altogether.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Live Streaming===&lt;br /&gt;
In order to enable live streaming, we need to include a module named ActionController::Live. When this module is mixed into the controller, all actions within that controller will be able to stream data to the client in real time, like the following code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MessageController &amp;lt; ApplicationController&lt;br /&gt;
 #here we enabled live streaming&lt;br /&gt;
 include ActionController::Live&lt;br /&gt;
 def message&lt;br /&gt;
   response.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/event-stream&amp;quot;&lt;br /&gt;
   10.times {&lt;br /&gt;
     response.stream.write &amp;quot;This is a live streaming message!\n&amp;quot;&lt;br /&gt;
     sleep 1&lt;br /&gt;
   }&lt;br /&gt;
 ensure&lt;br /&gt;
   response.stream.close&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above code looks exactly the same as the traditional response, except the newly included module ActionController::Live. Now data can be streamed to the client each time when write method is called. When we run the code above, the web page will print one line “This is a response message!” for every seconds and repeats 10 times.&amp;lt;ref&amp;gt;http://tenderlovemaking.com/2012/07/30/is-it-live.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Server-Sent Event==&lt;br /&gt;
Server-sent event (SSE) is a technology where browser can automatically receive update data from a server via HTTP connection. Whenever server sends data, the SSE method in the browser will trigger an event.The SSE EventSource API is standardized as part of HTML5 by the W3C. It can be used together with the Live API to achieve full-duplex communication.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Server-sent_events&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A simple SSE looks like the following :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'json' &lt;br /&gt;
module ServerSide&lt;br /&gt;
  class SSE&lt;br /&gt;
    def initialize io&lt;br /&gt;
      @io = io&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def write object, options = {}&lt;br /&gt;
      options.each do |k,v|&lt;br /&gt;
        @io.write &amp;quot;#{k}: #{v}n&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      @io.write &amp;quot;data: #{object}nn&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    def close&lt;br /&gt;
      @io.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This module assigns the I/O stream object to a hash and converts it into a key-value pair so that it is easy to read, store, and send it back in JSON format.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now we can wrap stream object inside the SSE class. By doing this, we need to include SSE module inside the controller, so that the opening and closing of connections will be managed by SSE module. And we also add the ensure clause to make sure that the connection will always be closed after execution.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
require 'sse' &lt;br /&gt;
class MessagingController &amp;lt; ApplicationController&lt;br /&gt;
  include ActionController::Live&lt;br /&gt;
 &lt;br /&gt;
  def stream&lt;br /&gt;
    response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    sse = SSE.new(response.stream)&lt;br /&gt;
    begin&lt;br /&gt;
      5.times {&lt;br /&gt;
        sse.write(“Streaming using SSE!”)&lt;br /&gt;
        sleep 1&lt;br /&gt;
      }&lt;br /&gt;
    ensure&lt;br /&gt;
      sse.close&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code above will print the sentence “Streaming using SSE!” once per second, until the loop ends.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here’s another sample showing how to use SSE to stream data&amp;lt;ref&amp;gt;https://github.com/rails/rails/blob/6061c540ac7880233a6e32de85cec72c20ed8778/actionpack/lib/action_controller/metal/live.rb&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    # This class provides the ability to write an SSE (Server Sent Event)&lt;br /&gt;
    # to an IO stream. The class is initialized with a stream and can be used&lt;br /&gt;
    # to either write a JSON string or an object which can be converted to JSON.&lt;br /&gt;
    #&lt;br /&gt;
    # Writing an object will convert it into standard SSE format with whatever&lt;br /&gt;
    # options you have configured. You may choose to set the following options:&lt;br /&gt;
    #&lt;br /&gt;
    #   1) Event. If specified, an event with this name will be dispatched on&lt;br /&gt;
    #   the browser.&lt;br /&gt;
    #   2) Retry. The reconnection time in milliseconds used when attempting&lt;br /&gt;
    #   to send the event.&lt;br /&gt;
    #   3) Id. If the connection dies while sending an SSE to the browser, then&lt;br /&gt;
    #   the server will receive a +Last-Event-ID+ header with value equal to +id+.&lt;br /&gt;
    #&lt;br /&gt;
    # After setting an option in the constructor of the SSE object, all future&lt;br /&gt;
    # SSEs sent across the stream will use those options unless overridden.&lt;br /&gt;
    #&lt;br /&gt;
    # Example Usage:&lt;br /&gt;
    #&lt;br /&gt;
    #   class MyController &amp;lt; ActionController::Base&lt;br /&gt;
    #     include ActionController::Live&lt;br /&gt;
    #&lt;br /&gt;
    #     def index&lt;br /&gt;
    #       response.headers['Content-Type'] = 'text/event-stream'&lt;br /&gt;
    #       sse = SSE.new(response.stream, retry: 300, event: &amp;quot;event-name&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'})&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;)&lt;br /&gt;
    #       sse.write({ name: 'John'}, id: 10, event: &amp;quot;other-event&amp;quot;, retry: 500)&lt;br /&gt;
    #     ensure&lt;br /&gt;
    #       sse.close&lt;br /&gt;
    #     end&lt;br /&gt;
    #   end&lt;br /&gt;
    #&lt;br /&gt;
    # Note: SSEs are not currently supported by IE. However, they are supported&lt;br /&gt;
    # by Chrome, Firefox, Opera, and Safari.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Note: By default Rails provides a one-way communication process by writing the stream to the client when data is available. However, if we can add SSEs, we can enable events and responses, thus making it two-way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Benefit of live streaming==&lt;br /&gt;
1.Send partial responses to the client immediately.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2.Using Server-sent events, the ability to create chat clients, push notifications, and real-time feeds are available within Rails itself&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
3.Continuously inform the user about the progress.&lt;br /&gt;
See example below&amp;lt;ref&amp;gt;http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def big_work&lt;br /&gt;
  work = WorkModel.new&lt;br /&gt;
  while !work.done?&lt;br /&gt;
    work.do_some_calculations&lt;br /&gt;
    response.stream.write &amp;quot;Progress: #{work.progress}%\n&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
  response.stream.close&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''Troubleshooting'''=&lt;br /&gt;
When running streaming programs, we need to install [http://puma.io/ PUMA] to substitute the original WEBrick server, because puma can handle concurrency better. In order to do this, we need to add the following line to Gemfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem 'puma'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
After installed puma, if we start rails server, the console will print the following output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;C:\Program Files (x86)\JetBrains\RubyMine 7.0.2\bin\runnerw.exe&amp;quot; C:\RailsInstaller\Ruby2.0.0\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/Cloud/Coding/RubymineProjects/LiveStreamingExample/bin/rails server -b 127.0.0.1 -p 3000 -e development&lt;br /&gt;
=&amp;gt; Booting Puma&lt;br /&gt;
=&amp;gt; Rails 4.1.8 application starting in development on http://127.0.0.1:3000&lt;br /&gt;
=&amp;gt; Run `rails server -h` for more startup options&lt;br /&gt;
=&amp;gt; Ctrl-C to shutdown server&lt;br /&gt;
Puma 2.11.0 starting...&lt;br /&gt;
* Min threads: 0, max threads: 16&lt;br /&gt;
* Environment: development&lt;br /&gt;
* Listening on tcp://127.0.0.1:3000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This means that PUMA is set as our default server and successfully booted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We encountered failure on Windows when trying to install PUMA, the console printed the following error:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Building native extensions.  This could take a while...&lt;br /&gt;
ERROR:  Error installing rails:&lt;br /&gt;
ERROR: Failed to build gem native extension.&lt;br /&gt;
&lt;br /&gt;
/Users/WillieTran/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb&lt;br /&gt;
*** extconf.rb failed ***&lt;br /&gt;
&lt;br /&gt;
Could not create Makefile due to some reason, probably lack of necessary&lt;br /&gt;
libraries and/or headers.  Check the mkmf.log file for more details.  You may&lt;br /&gt;
need configuration options.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
To solve this problem, we need to install [https://www.openssl.org/ openssl] for windows. And then run the following command&amp;lt;ref&amp;gt;https://github.com/hicknhack-software/rails-disco/wiki/Installing-puma-on-windows&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gem install puma -- --with-opt-dir=c:\openssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ylu31</name></author>
	</entry>
</feed>