CSC/ECE 517 Fall 2014/ch1b 34 kr: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
(68 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= '''Overview''' =
= '''AngularJS + Rails''' =


[http://angularjs.org// AngularJS] is an [http://en.wikipedia.org/wiki/Open_source open source] framework for creating web applications with [http://en.wikipedia.org/wiki/Dynamic_web_page dynamic web pages] and is maintained by [http://www.google.com/ Google]. AngularJS has extended [http://en.wikipedia.org/wiki/HTML HTML's] syntax and implemented it with [http://mrbool.com/mvc-in-angularjs/28962 MVC] architecture so that the various components of [http://en.wikipedia.org/wiki/JavaScript Javascript] can be expressed clearly. It provides functionalities like [http://docs.angularjs.org/guide/databinding data binding] and [http://docs.angularjs.org/guide/di dependency injection] which helps shorten the crude javascript code. It has a simple [http://en.wikipedia.org/wiki/Object_model object model] that supports testability and clean code organization.
==Overview==
 
[http://angularjs.org// AngularJS] is an [http://en.wikipedia.org/wiki/Open_source open source] client-side [http://en.wikipedia.org/wiki/JavaScript Javascript] framework for creating web applications with [http://en.wikipedia.org/wiki/Dynamic_web_page dynamic web pages] and is maintained by [http://www.google.com/ Google]. AngularJS has extended [http://en.wikipedia.org/wiki/HTML HTML's] syntax and implemented it with [http://mrbool.com/mvc-in-angularjs/28962 Model-View-Controller] architecture so that the various components of Javascript can be expressed clearly. It provides functionalities like [http://docs.angularjs.org/guide/databinding data binding] and [http://docs.angularjs.org/guide/di dependency injection] which helps shorten the crude javascript code. It has a simple [http://en.wikipedia.org/wiki/Object_model object model] that supports testability and clean code organization.<ref>http://code.tutsplus.com/tutorials/5-awesome-angularjs-features--net-25651</ref>
 
[http://rubyonrails.org/ Rails] is an open source web application framework written in [http://www.ruby-lang.org/en/ Ruby] by David Heinemeier Hansson. It is extremely productive for developing database-backed web applications. It uses Model-View-Controller architecture and requires fewer total lines of code than other frameworks thus making it atleast ten times faster.


{| border="1" class="wikitable" style="float:{{{align|right}}}"
{| border="1" class="wikitable" style="float:{{{align|right}}}"
|colspan="2" align="center" |[[File:Cherrypy.png|center|AngularJS + Rails<ref>http://rigor.com/wp-content/uploads/2014/09/angularjs+rails.jpg</ref>]]
|colspan="2" align="center" |[[File:angularjs+rails.jpg|center|AngularJS + Rails<ref>http://rigor.com/wp-content/uploads/2014/09/angularjs+rails.jpg</ref>]]
|-
|-
|'''Name'''||[http://www.cherrypy.org/ CherryPy]
|'''Name'''||[http://angularjs.org// AngularJS] + [http://rubyonrails.org/ Rails]
|-
|-
|'''Category'''||[http://en.wikipedia.org/wiki/Open-source_software Open Source Software]
|'''Category'''||[http://en.wikipedia.org/wiki/Open-source_software Open Source Software]
Line 12: Line 16:
|'''Type'''||[http://en.wikipedia.org/wiki/Web_application_framework Web Application Framework]
|'''Type'''||[http://en.wikipedia.org/wiki/Web_application_framework Web Application Framework]
|-
|-
|'''Developer(s)'''||[https://bitbucket.org/cherrypy/cherrypy/wiki/CherryPyTeam CherryPyTeam]
 
|-
|'''License'''||[https://en.wikipedia.org/wiki/BSD_licenses BSD]
|-
|'''Latest Stable Version'''||[https://cherrypy.readthedocs.org/en/3.3.0/intro/install.html#download-stable-versions 3.3.0 / April 16, 2014]
|-
|'''Written in'''||[http://en.wikipedia.org/wiki/Python_%28programming_language%29 Python]
|}
__TOC__
__TOC__


==Background==
==Background==
The CherryPy project v0.1 was founded and release by Remi Delon in Jul 2002<ref>http://freecode.com/projects/cherrypy/</ref> on [http://freecode.com/ FreeCode]. Version v2.0 released in May 2005 and was moved to [https://bitbucket.org/ BitBucket] from v2.1 onwards. Remi Delon is now works full time on [http://www.webfaction.com WebFaction] (which he also founded in 2003) although he is still recognized as project leader for CherryPy. Finally in Dec 2006 v3.0 came out with much of the original code rewritten under Robert Brewer as the lead developer.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/CherryPyTeam</ref><ref>https://docs.google.com/presentation/d/1NOGM5w1yu6dnXyEyYC4r6ZDuRgii4YaqlkrrlxfbnzM/edit?pli=1#slide=id.g178c5c5e9_032</ref>


{| border="1" class="wikitable" style="{{{align|right}}}"
===AngularJS===
|+Major Changes
 
|-
AngularJS was developed by Misko Hevery and Adam Abrons at Brat Tech LLC in 2009 as the software behind an oline JSON storage service. Later, it was released as an open source library. The library is being developed and maintained by Hevery with his fellow Google employees.
|'''v2.0'''|| Unpythonic features removed. There is no longer a compilation step; it is pure Python source code (no more "CherryClass"). <ref>http://freecode.com/projects/cherrypy/releases</ref>
 
|-
===Rails===
|'''v2.1'''||New HTTP servers, and [http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface WSGI] support. New Profiler module. New config system added<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn21</ref>
Rails was extracted from Basecamp, a project management tool by 37signals but it was released as an open source project in July 2004. It gained fame after Apple decided to ship it with Mac OS X, which was released in October 2007.
|-
|'''v2.2'''||Custom WSGI server support<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn22</ref>
|-
|'''v3.0'''||[[#Per-Request Functions (Tools)| Tools]] support. New Logger. Multiple HTTP server support. Considerable speedup.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn30</ref>
|-
|'''v3.1'''||[[#Server Wide Functions (Plugins)| Plugins]] support. [[#Deployment| cherryd]] script.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn31</ref>
|-
|'''v3.2'''|| Python 3 support.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn32</ref>
|}


==Installation==
==Why AngularJS + Rails?==


===History===
One of the key reasons of using AngularJs is API-Driven Application approach, i.e. separation of User Interface from back-end (Rails in our case). Increasing number of application these days (Rails Application) are building their own APIs which can they interface with mobile applications (like iOS), or other developer applications can communicate with their applications, and in our case to communicate with front-end applications. By following this paradigm, developers gets an opportunity to build a front-end as well as back-end APIs along with your application, it means front-end exposes its methods to the JSON API in the back-end and the front-end API can be clubbed with any back-end and vice-versa without any need for re-configuration.<ref>https://www.codeschool.com/courses/shaping-up-with-angular-js</ref>  
Because CherryPy is nothing more than a Python library, it needs a Python environment (Python 2.3 through to 3.4) and can also run on various implementations of Python including [http://en.wikipedia.org/wiki/IronPython IronPython] for [http://en.wikipedia.org/wiki/.NET_Framework .NET]  and [http://en.wikipedia.org/wiki/Jython Jython] for [http://en.wikipedia.org/wiki/Java_%28programming_language%29 Java].<ref>http://docs.cherrypy.org/en/latest/install.html</ref>


===Requirements===
So the question is why to club AngularJS with Rails and what are its advantages? AngularJS is a front-end framework, what this means is, it is designed to run on the client side, therefore for any real application requiring CRUD operations a back-end is necessary. This is where Rails comes into picture, it provides a back-end to the AngularJS application so that large amount of data can be stored in database. Another issue with using standalone AngularJS application is that it creates Single-page Applications (SPA), i.e. the same page or components on the page gets refreshed, which makes [http://en.wikipedia.org/wiki/Search_engine_optimization Search Engine Optimization] extremely tricky, as a result the possibility of making the web page searchable reduces drastically. Whereas in case of Rails the web pages are rendered by Rails on the server, which makes them available to Google for SEO based search.<ref>http://joelhooks.com/blog/2013/09/15/why-i-built-an-angularjs-training-site-on-rails</ref>
CherryPy requires a Python version between 2.3 and 3.4 inclusively. Certain features require packages but none are mandatory for installation.<ref>http://docs.cherrypy.org/en/latest/install.html</ref>
*[http://routes.readthedocs.org/en/latest/ routes] for declarative URL mapping dispatcher
*[http://pythonhosted.org//psycopg2/ psycopg2] for [http://en.wikipedia.org/wiki/PostgreSQL PostgreSQL] database backend session
*[http://sourceforge.net/projects/pywin32/ pywin32] for Windows services
*[https://github.com/linsomniac/python-memcached python-memcached] for [http://en.wikipedia.org/wiki/Memcached Memcached] backend session
*[https://github.com/simplejson/simplejson simplejson] for a better [http://en.wikipedia.org/wiki/JSON JSON] support
*[https://github.com/pyca/pyopenssl pyOpenSSL] if your Python environment does not have the built in [http://en.wikipedia.org/wiki/Transport_Layer_Security ssl] module


==Getting Started<ref>http://sebastien.saunier.me/blog/2014/02/04/angular--rails-with-no-fuss.html</ref>==
===Prerequisites===


===Installing===
=====AngularJS=====
CherryPy can be installed through common Python package managers with the following commands:<ref>http://docs.cherrypy.org/en/latest/install.html</ref><br/>


Install (choose on of the following commands appropriately):
Following are the pre-requisites for learning AngularJS:<ref>http://angular-rails.com/</ref>
    $ easy_install cherrypy
# Moderate knowledge of HTML, JavaScript and CSS.
    $ pip install cherrypy
# Basic Model-View-Controller concepts.
    $ yum install python-cherrypy
# The [http://en.wikipedia.org/wiki/Document_Object_Model Document Object Model].
    $ apt-get install python python-dev
# JavaScript functions, events, and error handling.


===Install via yum===
=====Rails=====
CherryPy is provided by the fedora base repository. In [http://en.wikipedia.org/wiki/Fedora_%28operating_system%29 Fedora] (and other [http://en.wikipedia.org/wiki/RPM_Package_Manager RPM] based Linux distributions, such as [http://en.wikipedia.org/wiki/CentOS CentOS] and [http://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux Red Hat Enterprise Linux]):<br/>
    $ yum install python-cherrypy


===Install via apt-get===
# Comprehensive knowledge of Ruby.
CherryPy is also provided in the [http://en.wikipedia.org/wiki/Ubuntu_(operating_system) Ubuntu] base repository. In Ubuntu (and other [http://en.wikipedia.org/wiki/Debian Debian]-based Linux distributions such as Debian and [http://en.wikipedia.org/wiki/Linux_Mint Linux Mint]):
# Moderate knowledge of databases.
    $ apt-get install python python-dev
# Basic Model-View-Controller concepts.


===Installation from source===
===Download AngularJS===
The source code is hosted on [http://en.wikipedia.org/wiki/Bitbucket BitBucket] and requires [http://en.wikipedia.org/wiki/Mercurial Mercurial] to pull and install from the site itself.
    $ hg clone https://bitbucket.org/cherrypy/cherrypy
    $ cd cherrypy
    $ python setup.py install


Alternatively, the source can be manually downloaded from [https://bitbucket.org/cherrypy/cherrypy/downloads here] in a tarball.
Download AngularJS from [https://angularjs.org/ AngularJS] website. We need to download file: angular-mocks.js
    $ tar -xvf CherryPy-#.#.#.tar.gz
    $ cd CherryPy-#.#.#
    $ python setup.py install


===Install for Windows===
===Step 1: Creating Base Rails app===
*If you are using Windows, install Linux and follow any of the a forementioned methods.
*If you absolutely must use windows, you can download the .exe file to install CherryPy from [https://bitbucket.org/cherrypy/cherrypy/downloads here].


==Interface==
We will start with creating a basic Rails application that performs CRUD operations. We shall use PostgreSQL and Rspec here.


CherryPy is meant to be pythonic, meaning that development time  is meant to be minimized and code is meant to be sparse and clean <ref>http://docs.cherrypy.org/en/latest/intro.html</ref>
Lets call this application: Restauranteur <ref>http://www.honeybadger.io/blog/2013/12/11/beginners-guide-to-angular-js-rails</ref>


===Basic Example===
====Initial Setup====
Lets look at a hello world example<ref>https://cherrypy.readthedocs.org/en/3.2.6/concepts/basics.html</ref><ref>http://stackoverflow.com/questions/419163/what-does-if-name-main-do</ref>
To create project:
<pre>
<pre>
#Use the cherrypy python library
$ rails new restauranteur --database=postgresql --skip-test-unit
import cherrypy
</pre>


#Hello World project
To create PostgresSQL user:
class HelloWorld(object):


#  index page
<pre>
    def index(self):
$ createuser -P -s -e restauranteur
#      Return the page contents
</pre>
        return “Hello World!”


#  Allow the page to be visible
Add Rspec to your Gemfile:
    index.exposed = True
<pre>
gem "rspec-rails", "~> 2.14.0"
</pre>


#designates this module as main
Install Rspec
if __name__ == ‘__main__’:
<pre>
$ bundle install
$ rails g rspec:install
</pre>


#  instantiates app and starts server
Create the database:
    cherrypy.quickstart(HelloWorld())
<pre>
$ rake db:create
</pre>


===Step 2: Creating the Restaurant model===
Our next step is to create a model class in Rails
<pre>
$ rails generate scaffold restaurant name:string
</pre>
</pre>
The above script sets up a basic Hello World application, by defining the index page (http://localhost:8080/) as an object that returns the string “Hello World!”. The page is exposed, meaning that the method can be called to answer a [http://en.wikipedia.org/wiki/Representational_state_transfer RESTful] request. Otherwise, the method is internal only. This is similar to making a method public in Java. <ref>http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html</ref>


===Routing, Parameters, and Exposure===
Make sure that Restaurant Names are unique:
Routing is the act of finding the appropriate code to handle a request. CherryPy uses a dispatcher to perform most of these, but premade dispatchers exist to handle more sophisticated handling of request. The most common is a page handler (the name of the object). Parameters can be passed into the handler via http query strings. These strings are appended to the URL of a site after a "?". Exposure is just the way CherryPy prevents access to objects from the users. Without the exposed attribute set to true, an object won't be accessible to the user.
<pre>
<pre>
#import python library
# db/migrate/[timestamp]_create_restaurants.rb
import cherrypy


#More Routes application
class CreateRestaurants < ActiveRecord::Migration
class MoreRoutes(object):
  def change
    create_table :restaurants do |t|
      t.string :name


#  Method decorator for index and equates to index.exposed = True
      t.timestamps
     @cherrypy.expose
     end
    def index(self):
        return "Hello world!"


#   http://localhost:8080/route1
    # Add the following line
    def route1(self, id=”charles”):
    add_index :restaurants, :name, unique: true
#      http://localhost:8080/route1?id=somestring
  end
        return “Your name is ” + id
end
</pre>


#   Params passed as a GET request.
Add this in Model:
#  Default string is “charles”
<pre>
    route1.exposed = True
class Restaurant < ActiveRecord::Base
   validates :name, presence: true, uniqueness: { case_sensitive: false }
end
</pre>


#  No explicit indication of exposure so calling this route will generate a 404 error
then run Migration
    def route2(self):
<pre>
        return “Still another one”
$ rake db:migrate
</pre>


if __name__ == '__main__':
and finally Seed the database:
    cherrypy.quickstart(MoreRoutes())
<pre>
# db/seeds.rb


Restaurant.create([
  { name: "The French Laundry" },
  { name: "Chez Panisse" },
  { name: "Bouchon" },
  { name: "Noma" },
  { name: "Taco Bell" },
])
</pre>
</pre>


The above shows how multiple routes are handled from the Hello World application and the expose decorator. Since route2 is not exposed, the user can not access it and will be shown a 404 HTTP status code (Not Found error).
===Step 3: Introduce AngularJS ===
Now we need to make use of the downloaded AngularJS, and move the files into app/assets/javascripts.


===Multiple Applications===
Add it to Asset Pipeline, to tell our application we need AngularJs and to make sure it gets loaded before other dependent files. Add the following lines:
<pre>
//= require angular
//= require main
</pre>


Now, AngularJS being an MVC framework requires its own '''Controller'''. Now we will create controller for it in directory /assets/javascripts/angular/controllers. Let's call the controller '''HomeCtrl'''


<pre>
<pre>
import cherrypy
# app/assets/javascripts/angular/controllers/HomeCtrl.js.coffee
#blog module
class Blog(object):
    ...<blog code>...
#forum module
class Forum(object):
    ...<forum code>...
#”main” method
if __name__ == '__main__':
#designates the blog to be under /blog route
    cherrypy.tree.mount(Blog(), ‘/blog’, “blog.conf”)
#designates the forum to be under /forum route
    cherrypy.tree.mount(Forum(), ‘/forum’, “forum.conf”)
</pre> <ref>http://docs.cherrypy.org/en/latest/basics.html#multiple-applications</ref>
In the above example, the blog would be found under /blog in the URL, wheras the forum will be mounted at /forum in the application tree. The XXX.conf files are configuration files, which are dictionaries containing string keys and polymorphic values and can be used to set attributes on the engine, server, request, response, and log objects. <ref>https://cherrypy.readthedocs.org/en/3.2.6/concepts/config.html</ref>


===Database Support===
@restauranteur.controller 'HomeCtrl', ['$scope', ($scope) ->
CherryPy offers multiple database integration possibilities including
  # Notice how this controller body is empty
*[http://en.wikipedia.org/wiki/Relational_database Relational]: [http://en.wikipedia.org/wiki/PostgreSQL PostgreSQL], [http://en.wikipedia.org/wiki/SQLite SQLite], [http://en.wikipedia.org/wiki/MariaDB MariaDB], [http://en.wikipedia.org/wiki/Firebird_%28database_server%29 Firebird]
]
*[http://en.wikipedia.org/wiki/Column-oriented_DBMS Column-Oriented]: [http://en.wikipedia.org/wiki/Apache_HBase HBase], [http://en.wikipedia.org/wiki/Apache_Cassandra Cassandra]
*[http://en.wikipedia.org/wiki/NoSQL#Key.E2.80.93value_stores Key-Store]: [http://en.wikipedia.org/wiki/Redis Redis], [http://en.wikipedia.org/wiki/Memcached Memcached]
*[http://en.wikipedia.org/wiki/Document-oriented_database Document-Oriented]: [http://en.wikipedia.org/wiki/CouchDB Couchdb], [http://en.wikipedia.org/wiki/MongoDB MongoDB]
*[http://en.wikipedia.org/wiki/Graph_database Graph-Oriented]: [http://en.wikipedia.org/wiki/Neo4j Neo4j]<br/>
Unfortunately, unlike [https://en.wikipedia.org/wiki/Ruby_on_Rails Ruby on Rails], CherryPy does not have a sophisticated [https://en.wikipedia.org/wiki/Active_record_pattern#Ruby Active Record Pattern] based class for database abstraction, and the database connection has to be established manually. The queries are constructed as static [https://en.wikipedia.org/wiki/SQL SQL] strings with values concatenated during function calls.<br/>


Here is an example of how it would look like<ref>http://cherrypy.readthedocs.org/en/latest/tutorials.html#tutorial-9-data-is-all-my-life</ref>
</pre>
 
===Step 4: Create Templates and Modify Controller ===
 
Make changes in the layout:
<pre>
<pre>
<!-- app/views/layouts/application.html.erb -->


# import the Handles
<html>        ==>  <html ng-app="restauranteur">
import MySQLdb
import cherrypy


# defining the connection function
<%= yield %>  ==>   <div ng-view> <%= yield %> </div>
def connect(thread_index):
</pre>
#   Create a connection and store it in the current thread
    cherrypy.thread_data.db = MySQLdb.connect('host', 'user', 'password', 'dbname')


# tell cherrypy to  call connect function for each thread
Make template for restaurants (this can be created anywhere), we are making it under public directory and create and index page:
cherrypy.engine.subscribe('start_thread', connect)


# example query function
<pre>
@cherrypy.expose
<!-- public/templates/restaurants/index.html -->
def count(val)
#  fetching instance of db connection
    c = cherrypy.thread_data.db.cursor()
#  executing query
    c.execute( 'select count(‘ + val + ’) from table' )
#  fetching results from db
    res = c.fetchone()
#  releasing instance of the connection
    c.close()
#  returning the count value
    return res


<a href="/#">index</a>
<ul ng-repeat="restaurant in restaurants">
  <li><a ng-click="viewRestaurant(restaurant.id)">{{ restaurant.name }}</a></li>
</ul>
</pre>
</pre>


==RESTful CherryPy==
create Restaurant Index Controller
[http://en.wikipedia.org/wiki/Representational_state_transfer REST] (Representational State Transfer) is an abstraction of the architectural elements within a distributed hypermedia system. It ignores the details of component implementation and protocol syntax in order to focus on the roles of components, the constraints upon their interaction with other components, and their interpretation of significant data elements. It encompasses the fundamental constraints upon components, connectors, and data that define the basis of the Web architecture, and thus the essence of its behavior as a network-based application. <ref>http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm</ref><br/>
<pre>
In othe words, REST is defined by four interface constraints: identification of resources, manipulation of resources through representations, self-descriptive messages, and hypermedia as the engine of application state.<ref>https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html</ref>
# app/assets/javascripts/angular/controllers/RestaurantIndexCtrl.js.coffee
 
@restauranteur.controller 'RestaurantIndexCtrl', ['$scope', '$location', '$http', ($scope, $location, $http) ->
  $scope.restaurants = []
  $http.get('./restaurants.json').success((data) ->
    $scope.restaurants = data
  )
]
</pre>


===Identification of Resources===
===Step 5: Adjust Routing in main.js===
Since Cherrypy is an HTTP service provider, resources are referenced by HTTP URIs (Uniform Resource Identifiers), which consist of a scheme, hierarchical identitfier, query, and fragment.<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#implementing-rest-in-cherrypy</ref><br/>
*Scheme: in [http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol http], the scheme is always http or [http://en.wikipedia.org/wiki/HTTP_Secure https].
*Hierarchical Identifier: consists of an authority and a path (host/port and a path similar to the system file path but not the actual path). The path is mapped to Python Objects via a dispatch mechanism.


===Manipulation of Resources Through Representations===
Now modify routing so that new Restaurant Index page is called.
The standard [http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html HTTP methods] are as follows<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#manipulation-of-resources-through-representations</ref>
*<code>GET</code> retrieves the state of a specific resource
*<code>PUT</code> creates or replaces the state of a specific resource
*<code>POST</code> passes information to a resource to use as it sees fit
*<code>DELETE</code> removes resources


===Self-Descriptive Messages===
<pre>
REST requires messages to be self-descriptive, meaning everything about a message is within the message itself. Such information can be found in the method headers or the definitions of the message’s media type. cherrypy.request.headers and cherrypy.response.headers are used to get this information. Custom-Types are allowed as well.<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#self-descriptive-messages</ref>
# app/assets/javascripts/main.js.coffee


===Hypermedia as the Engine of the Application State===
@restauranteur = angular.module('restauranteur', [])
Since REST is stateless and the state is maintained by the application in question, sessions are not maintained by REST, so, by association, CherryPy does not enable sessions by default. However, the REST server helps clients maintain a meaningful state through meaningful URIs<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#hypermedia-as-the-engine-of-application-state</ref>


==Crash Course==
@restauranteur.config(['$routeProvider', ($routeProvider) ->
  $routeProvider.
    when('/restaurants', {
      templateUrl: '../templates/restaurants/index.html',
      controller: 'RestaurantIndexCtrl'
    })
])
</pre>


It's done! Now go to URI /#/restaurants to see list of Restaurants we added.


==Testing==
For testing we are going to use Rspec, Karma, and Jasmine framework. We start by first installing Karma server:


===Development===
====For Ubuntu====
Create an application. Application requirements:
<pre>
*The module needs to define a <code>__main__ </code>
sudo npm install -g karma
*<code>cherrypy.quickstart(<Application Name>())</code> for hosting a single application. For example: cherrypy.quickstart(Blog())
sudo npm install -g karma-ng-scenario
*<code>cherrypy.tree.mount(<Application Name>(), ‘/<hosting path segment>’, <configuration>)</code> for hosting multiple applications. For example: <code>cherrypy.tree.mount(Blog(), ‘/blog’, blog_conf) </code>
</pre>
*All parts the users will see must be exposed with either the decorator <code>@cherrypy.expose or attribues exposed = True</code> or <code>route.exposed = True.</code>


====For Windows====
Install via Git bash
<pre>
<pre>
import cherrypy
npm install -g karma
class HelloWorld(object):
    def index(self):
        return “Hello World!”
    index.exposed = True
if __name__ == ‘__main__’:
    cherrypy.quickstart(HelloWorld())
</pre>
</pre>


===Deployment===
===Step by step Testing Procedure===
The application can be run as a python script in the Python interpreter.
Create Test Folder
    $ python <app file>.py
<pre>
It will hosted at http://127.0.0.1:8080/
mkdir spec/javascripts
It can also be run as a daemon process with
</pre>
    $cherryd -c <config file> -d -p <PID file>


==Testing==
Write Tests
CherryPy provides a helper class for testing. The feature of the framework is that test are run against a running cherrypy server and testing small cmponents without actually starting the server is not natively suported.
<pre>
# spec/javascripts/controllers_spec.js.coffee
 
describe "Restauranteur controllers", ->
  beforeEach module("restauranteur")


Lets look at an example<ref>http://cherrypy.readthedocs.org/en/latest/advanced.html#testing-your-application</ref>
  describe "RestaurantIndexCtrl", ->
    it "should set restaurants to an empty array", inject(($controller) ->
      scope = {}
      ctrl = $controller("RestaurantIndexCtrl",
        $scope: scope
      )
      expect(scope.restaurants.length).toBe 0
    )
</pre>


Add Configurations
<pre>
<pre>
#importing cherrypy library
// spec/javascripts/restauranteur.conf.js
import cherrypy
 
module.exports = function(config) {
  config.set({
    basePath: '../..',
 
    frameworks: ['jasmine'],


#importing the helper class
    autoWatch: true,
from cherrypy.test import helper


#creating a simple test class
    preprocessors: {
class SimpleCPTest(helper.CPWebCase):
      '**/*.coffee': 'coffee'
    },


#  function to start the cherrypy server
    files: [
     def setup_server():
      'app/assets/javascripts/angular.js',
      'app/assets/javascripts/angular-mocks.js',
      'app/assets/javascripts/angular/controllers/RestaurantIndexCtrl.js.coffee',
      'app/assets/javascripts/angular/*',
      'spec/javascripts/*_spec.js.coffee'
    
  });
};
</pre>


#      root class of application  to be tested
Start Karma Server
        class Root(object):
<pre>
karma start spec/javascripts/restauranteur.conf.js
</pre>


#          the expose method which we are trying to test
Go to go to http://localhost:9876/ and test will run and be successful.
#          this method will respond to localhost/echo and actually echo the argument sent to it
            @cherrypy.expose
            def echo(self, message):
                return message


#      settingup the root class to be created on server start
==Comparison with other front-end frameworks==
        cherrypy.tree.mount(Root())


#  grabbing the decorator for starting the server
The most popular front end frameworks these days include AngularJS, [http://backbonejs.org/ BackboneJS] and [http://emberjs.com/ EmberJS]. These can be compared on the basis of the following factors<ref>http://www.airpair.com/js/javascript-framework-comparison</ref>:
    setup_server = staticmethod(setup_server)


#  This is the actual test code
===Community===
    def test_message_should_be_returned_as_is(self):


#      sending arguments to the echo method via html request
Community is the most important factor to consider when choosing a framework as a strong and large community means strong support and help towards the framework. More questions will be answered, more tutorials will be available. In short, larger the community means more the number of resources to exploit.  
        self.getPage("/echo?message=Hello%20world")


#      chechink if server accepted our request
So, if compared on the basis of community, AngularJS is the clear winner as there are more [http://stackoverflow.com/questions/tagged/angularjs StackOverflow questions] , [https://www.youtube.com/user/angularjs YouTube tutorials], [http://github.com/ GitHub] Contributors available for Angular then the rest of the frameworks. Also, in the recent years AngularJS has gained more and more popularity compared to the other two.
        self.assertStatus('200 OK')


#      cheching response from server
===Framework Size===
        self.assertHeader('Content-Type', 'text/html;charset=utf-8')


#      checking if the was an "Hello World" in the response from server
For a website to be successful, it should have good page load speed as users these days need good speed of browsing. In order to load pages fast, the front end framework should be as small as possible so that they can be loaded faster.
        self.assertBody('Hello world')
If we compare the sizes of the frameworks, BackboneJS (6.5 kb) is the smallest among AngularJS(39.5 kb) and EmberJS(90 kb). But, BackboneJS needs UnderscoreJS(5 kb) and jQuery(32 kb) along with some other third party plugins which makes the size large.
Thus, AngularJS is the clear winner among these frameworks.


</pre>
===Templating===


==Extensions==
Front end frameworks generally use different kind of templates to style their code in a specific way. There are many kinds of [http://www.creativebloq.com/web-design/templating-engines-9134396 templates] available that an be used.
BackboneJS doesn't provide any templating engine of its own but AngularJS and EmberJS have there own templating system. The difference between the templating engines of the three frameworks can be understood from the following examples :


CherryPy provides a flexible open framework. Similar to [http://en.wikipedia.org/wiki/RubyGems RubyGems] in [http://en.wikipedia.org/wiki/Ruby_on_Rails Ruby on Rails] which add a range of functionality to the framework CherryPy also supports plugins in the the following forms
=====AngularJS=====


===Server Wide Functions (Plugins)===
Angular's templating engine simply extends HTML syntax. It uses [https://docs.angularjs.org/guide/expression binding expressions] to bind variables between controllers  and models. These binding expressions are enclosed by doubly curly braces. For example:
This type of extension is typically used to provide the application server itself with additional functionality. Such functions are executed with respect to events in the server even when there is no client request processing taking place.<ref>http://docs.cherrypy.org/en/latest/extend.html#id13</ref><br/>
Typical use case involve
*Background Tasks (Tasks which involve server mentainance, data management etc. which are independent of user requests)
*External Connections (For establishing and maintaining threaded connections to external database or other servers)
*Delayed/Queued Processing (Cases when certain tasks are required by the user request which take a long time process and the HTTP response should not be blocked.)<br/>
These function utilize the [http://en.wikipedia.org/wiki/Publish–subscribe_pattern Publish-Subscribe Framework] implementation of CherryPy. Each function subscribes to one or more events on the bus which are published by the CherryPy engine.<br/> The database connection is a good example of such a function<br/>


<pre>
<pre>
# import the Handles
<ul>
import MySQLdb
  <li ng-repeat="recipe in recipes"
import cherrypy
    title="{{recipe.title}}">
# defining the connection function
    {{recipe.description}}
def connect(thread_index):
  </li>
    # Create a connection and store it in the current thread
</ul>
    cherrypy.thread_data.db = MySQLdb.connect('host', 'user', 'password', 'dbname')
</pre>
 
=====EmberJS=====


# tell cherrypy to  call connect function for each thread
EmberJS uses [http://handlebarsjs.com/ Handlebars] template engine. Handlebars is an extension of [http://mustache.github.io/ Mustache] templating engine. It does not understand the [http://en.wikipedia.org/wiki/Document_Object_Model Document Object Model] structure so it is not aware of the context in which it is being used. It just does the simple string transformation. Another templating engine is being developed called [http://talks.erikbryn.com/htmlbars HTMLBars] which works on these flaws of the Handlebars. Since, HTMLBars is not yet ready therefore Handlebars is  currently being used. For example:
cherrypy.engine.subscribe('start_thread', connect)
 
<pre>
<ul>
  {{#each recipes}}
    <li {{bind-attr title=name}}>
        {{desc}}
    </li>
  {{/each}}
</ul>
</pre>
</pre>


Here the function connect subscribes to the <code>start_thread</code> channel. An event is published on the <code>start_thread</code> channel whenever a server thread is started. Here <code>engine</code> is the central bus of the CherryPy server.<br/>
=====BackboneJS=====
Similarly it is also possible to create new channels and even buses themselves.


===Per-Request Functions (Tools)===
BackboneJS doesn't have any templating engine of its own but it can be integrated with many third party templating engines. Since, [http://underscorejs.org/ Underscore] is a Backbone dependency so it is used by default for the templating purposes. But, underscore has a very basic templating engine and it has to be used in the mix with javascript. For example:  
This type of extension is typically used to insert functionality between stages of request processing. Also known as [http://docs.cherrypy.org/en/latest/extend.html#tools Tools] these are simple call-back functions registered with a [http://docs.cherrypy.org/en/latest/extend.html#hookpoint Hook Point]. Hook Points are predefined stages of request processing. CherryPy provides a [http://tools.cherrypy.org/ Default ToolBox] containing many tools. Users have the freedom to create their own tools and add them to the default toolbox or create a new one.<ref>http://docs.cherrypy.org/en/latest/extend.html#per-request-functions</ref><br/>
An example for creating a tool


<pre>
<pre>
# defining the function to be called
<ul>
def my_tool():
  <% _.each(recipes, function(recipe) { %>
    # put tool functunality here
    <li title="<%- recipe.name %>">
    print (“Super Amazing Tool”);
      <%- recipe.desc %>
    </li>
  <% }); %>
</ul>
</pre>


# creating the decorator for the tool
==Reference Material==
# specifying the hook point and function to be called
cherrypy.tools.mytool = cherrypy.Tool(‘on_end_request’, my_tool())


#Sample Usage
Following are the references to learn Ruby on which Rails is based :


class Root(object):
#[http://rubymonk.com/ Ruby Monk]
@cherrypy.expose()
#[http://rubylearning.com/ Ruby Learning]
@cherrypy.tools.mytool()
def index()
    return “Hello World”
</pre>


==Watch It In Action==
Following are the references to learn Rails :


CherryPy is used as a building block for [http://www.hulu.com/ Hulu]<ref>http://tech.hulu.com/blog/2013/03/13/python-and-hulu</ref> and [https://www.netflix.com/ Netflix]<ref>http://techblog.netflix.com/2013/03/python-at-netflix.html</ref>
#[http://railsforzombies.org/ Rails for Zombies]
#[http://www.railstutorial.org/book Ruby on Rails Tutorial]
#[http://guides.rubyonrails.org/index.html Rails Guides]


==Further Reading==
Following are the references to learn AngularJS :
[https://docs.google.com/presentation/d/1NOGM5w1yu6dnXyEyYC4r6ZDuRgii4YaqlkrrlxfbnzM/edit?pli=1#slide=id.p PowerPoint Presentation]


#[http://angularjs.org/ AngularJS]
#[http://www.w3schools.com/angular/ AngularJS Tutorials]
#[http://egghead.io/lessons AngularJS Training Videos]


==References==
==References==
<references/>
<references/>

Latest revision as of 04:37, 15 October 2014

AngularJS + Rails

Overview

AngularJS is an open source client-side Javascript framework for creating web applications with dynamic web pages and is maintained by Google. AngularJS has extended HTML's syntax and implemented it with Model-View-Controller architecture so that the various components of Javascript can be expressed clearly. It provides functionalities like data binding and dependency injection which helps shorten the crude javascript code. It has a simple object model that supports testability and clean code organization.<ref>http://code.tutsplus.com/tutorials/5-awesome-angularjs-features--net-25651</ref>

Rails is an open source web application framework written in Ruby by David Heinemeier Hansson. It is extremely productive for developing database-backed web applications. It uses Model-View-Controller architecture and requires fewer total lines of code than other frameworks thus making it atleast ten times faster.

Background

AngularJS

AngularJS was developed by Misko Hevery and Adam Abrons at Brat Tech LLC in 2009 as the software behind an oline JSON storage service. Later, it was released as an open source library. The library is being developed and maintained by Hevery with his fellow Google employees.

Rails

Rails was extracted from Basecamp, a project management tool by 37signals but it was released as an open source project in July 2004. It gained fame after Apple decided to ship it with Mac OS X, which was released in October 2007.

Why AngularJS + Rails?

One of the key reasons of using AngularJs is API-Driven Application approach, i.e. separation of User Interface from back-end (Rails in our case). Increasing number of application these days (Rails Application) are building their own APIs which can they interface with mobile applications (like iOS), or other developer applications can communicate with their applications, and in our case to communicate with front-end applications. By following this paradigm, developers gets an opportunity to build a front-end as well as back-end APIs along with your application, it means front-end exposes its methods to the JSON API in the back-end and the front-end API can be clubbed with any back-end and vice-versa without any need for re-configuration.<ref>https://www.codeschool.com/courses/shaping-up-with-angular-js</ref>

So the question is why to club AngularJS with Rails and what are its advantages? AngularJS is a front-end framework, what this means is, it is designed to run on the client side, therefore for any real application requiring CRUD operations a back-end is necessary. This is where Rails comes into picture, it provides a back-end to the AngularJS application so that large amount of data can be stored in database. Another issue with using standalone AngularJS application is that it creates Single-page Applications (SPA), i.e. the same page or components on the page gets refreshed, which makes Search Engine Optimization extremely tricky, as a result the possibility of making the web page searchable reduces drastically. Whereas in case of Rails the web pages are rendered by Rails on the server, which makes them available to Google for SEO based search.<ref>http://joelhooks.com/blog/2013/09/15/why-i-built-an-angularjs-training-site-on-rails</ref>

Getting Started<ref>http://sebastien.saunier.me/blog/2014/02/04/angular--rails-with-no-fuss.html</ref>

Prerequisites

AngularJS

Following are the pre-requisites for learning AngularJS:<ref>http://angular-rails.com/</ref>

  1. Moderate knowledge of HTML, JavaScript and CSS.
  2. Basic Model-View-Controller concepts.
  3. The Document Object Model.
  4. JavaScript functions, events, and error handling.
Rails
  1. Comprehensive knowledge of Ruby.
  2. Moderate knowledge of databases.
  3. Basic Model-View-Controller concepts.

Download AngularJS

Download AngularJS from AngularJS website. We need to download file: angular-mocks.js

Step 1: Creating Base Rails app

We will start with creating a basic Rails application that performs CRUD operations. We shall use PostgreSQL and Rspec here.

Lets call this application: Restauranteur <ref>http://www.honeybadger.io/blog/2013/12/11/beginners-guide-to-angular-js-rails</ref>

Initial Setup

To create project:

$ rails new restauranteur --database=postgresql --skip-test-unit

To create PostgresSQL user:

$ createuser -P -s -e restauranteur

Add Rspec to your Gemfile:

gem "rspec-rails", "~> 2.14.0"

Install Rspec

$ bundle install
$ rails g rspec:install

Create the database:

$ rake db:create

Step 2: Creating the Restaurant model

Our next step is to create a model class in Rails

$ rails generate scaffold restaurant name:string

Make sure that Restaurant Names are unique:

# db/migrate/[timestamp]_create_restaurants.rb

class CreateRestaurants < ActiveRecord::Migration
  def change
    create_table :restaurants do |t|
      t.string :name

      t.timestamps
    end

    # Add the following line
    add_index :restaurants, :name, unique: true
  end
end

Add this in Model:

class Restaurant < ActiveRecord::Base 
  validates :name, presence: true, uniqueness: { case_sensitive: false }
end

then run Migration

$ rake db:migrate

and finally Seed the database:

# db/seeds.rb

Restaurant.create([
  { name: "The French Laundry" },
  { name: "Chez Panisse" },
  { name: "Bouchon" },
  { name: "Noma" },
  { name: "Taco Bell" },
])

Step 3: Introduce AngularJS

Now we need to make use of the downloaded AngularJS, and move the files into app/assets/javascripts.

Add it to Asset Pipeline, to tell our application we need AngularJs and to make sure it gets loaded before other dependent files. Add the following lines:

//= require angular
//= require main

Now, AngularJS being an MVC framework requires its own Controller. Now we will create controller for it in directory /assets/javascripts/angular/controllers. Let's call the controller HomeCtrl

# app/assets/javascripts/angular/controllers/HomeCtrl.js.coffee

@restauranteur.controller 'HomeCtrl', ['$scope', ($scope) ->
  # Notice how this controller body is empty
]

Step 4: Create Templates and Modify Controller

Make changes in the layout:

<!-- app/views/layouts/application.html.erb -->

<html>         ==>   <html ng-app="restauranteur">

<%= yield %>   ==>   <div ng-view> <%= yield %> </div>

Make template for restaurants (this can be created anywhere), we are making it under public directory and create and index page:

<!-- public/templates/restaurants/index.html -->

<a href="/#">index</a>
<ul ng-repeat="restaurant in restaurants">
  <li><a ng-click="viewRestaurant(restaurant.id)">{{ restaurant.name }}</a></li>
</ul>

create Restaurant Index Controller

# app/assets/javascripts/angular/controllers/RestaurantIndexCtrl.js.coffee

@restauranteur.controller 'RestaurantIndexCtrl', ['$scope', '$location', '$http', ($scope, $location, $http) ->
  $scope.restaurants = []
  $http.get('./restaurants.json').success((data) ->
    $scope.restaurants = data
  )
]

Step 5: Adjust Routing in main.js

Now modify routing so that new Restaurant Index page is called.

# app/assets/javascripts/main.js.coffee

@restauranteur = angular.module('restauranteur', [])

@restauranteur.config(['$routeProvider', ($routeProvider) ->
  $routeProvider.
    when('/restaurants', {
      templateUrl: '../templates/restaurants/index.html',
      controller: 'RestaurantIndexCtrl'
    })
])

It's done! Now go to URI /#/restaurants to see list of Restaurants we added.

Testing

For testing we are going to use Rspec, Karma, and Jasmine framework. We start by first installing Karma server:

For Ubuntu

sudo npm install -g karma
sudo npm install -g karma-ng-scenario

For Windows

Install via Git bash

npm install -g karma

Step by step Testing Procedure

Create Test Folder

mkdir spec/javascripts

Write Tests

# spec/javascripts/controllers_spec.js.coffee

describe "Restauranteur controllers", ->
  beforeEach module("restauranteur")

  describe "RestaurantIndexCtrl", ->
    it "should set restaurants to an empty array", inject(($controller) ->
      scope = {}
      ctrl = $controller("RestaurantIndexCtrl",
        $scope: scope
      )
      expect(scope.restaurants.length).toBe 0
    )

Add Configurations

// spec/javascripts/restauranteur.conf.js

module.exports = function(config) {
  config.set({
    basePath: '../..',

    frameworks: ['jasmine'],

    autoWatch: true,

    preprocessors: {
      '**/*.coffee': 'coffee'
    }, 

    files: [
      'app/assets/javascripts/angular.js',
      'app/assets/javascripts/angular-mocks.js',
      'app/assets/javascripts/angular/controllers/RestaurantIndexCtrl.js.coffee',
      'app/assets/javascripts/angular/*',
      'spec/javascripts/*_spec.js.coffee'
    ]  
  });
};

Start Karma Server

karma start spec/javascripts/restauranteur.conf.js

Go to go to http://localhost:9876/ and test will run and be successful.

Comparison with other front-end frameworks

The most popular front end frameworks these days include AngularJS, BackboneJS and EmberJS. These can be compared on the basis of the following factors<ref>http://www.airpair.com/js/javascript-framework-comparison</ref>:

Community

Community is the most important factor to consider when choosing a framework as a strong and large community means strong support and help towards the framework. More questions will be answered, more tutorials will be available. In short, larger the community means more the number of resources to exploit.

So, if compared on the basis of community, AngularJS is the clear winner as there are more StackOverflow questions , YouTube tutorials, GitHub Contributors available for Angular then the rest of the frameworks. Also, in the recent years AngularJS has gained more and more popularity compared to the other two.

Framework Size

For a website to be successful, it should have good page load speed as users these days need good speed of browsing. In order to load pages fast, the front end framework should be as small as possible so that they can be loaded faster. If we compare the sizes of the frameworks, BackboneJS (6.5 kb) is the smallest among AngularJS(39.5 kb) and EmberJS(90 kb). But, BackboneJS needs UnderscoreJS(5 kb) and jQuery(32 kb) along with some other third party plugins which makes the size large. Thus, AngularJS is the clear winner among these frameworks.

Templating

Front end frameworks generally use different kind of templates to style their code in a specific way. There are many kinds of templates available that an be used. BackboneJS doesn't provide any templating engine of its own but AngularJS and EmberJS have there own templating system. The difference between the templating engines of the three frameworks can be understood from the following examples :

AngularJS

Angular's templating engine simply extends HTML syntax. It uses binding expressions to bind variables between controllers and models. These binding expressions are enclosed by doubly curly braces. For example:

<ul> 
  <li ng-repeat="recipe in recipes" 
     title="{{recipe.title}}"> 
    {{recipe.description}} 
  </li> 
</ul>
EmberJS

EmberJS uses Handlebars template engine. Handlebars is an extension of Mustache templating engine. It does not understand the Document Object Model structure so it is not aware of the context in which it is being used. It just does the simple string transformation. Another templating engine is being developed called HTMLBars which works on these flaws of the Handlebars. Since, HTMLBars is not yet ready therefore Handlebars is currently being used. For example:

<ul>
   {{#each recipes}}
     <li {{bind-attr title=name}}>
        {{desc}}
     </li>
   {{/each}}
</ul>
BackboneJS

BackboneJS doesn't have any templating engine of its own but it can be integrated with many third party templating engines. Since, Underscore is a Backbone dependency so it is used by default for the templating purposes. But, underscore has a very basic templating engine and it has to be used in the mix with javascript. For example:

<ul>
   <% _.each(recipes, function(recipe) { %> 
     <li title="<%- recipe.name %>"> 
       <%- recipe.desc %> 
     </li> 
   <% }); %>
</ul>

Reference Material

Following are the references to learn Ruby on which Rails is based :

  1. Ruby Monk
  2. Ruby Learning

Following are the references to learn Rails :

  1. Rails for Zombies
  2. Ruby on Rails Tutorial
  3. Rails Guides

Following are the references to learn AngularJS :

  1. AngularJS
  2. AngularJS Tutorials
  3. AngularJS Training Videos

References

<references/>

AngularJS + Rails<ref>http://rigor.com/wp-content/uploads/2014/09/angularjs+rails.jpg</ref>
AngularJS + Rails<ref>http://rigor.com/wp-content/uploads/2014/09/angularjs+rails.jpg</ref>
Name AngularJS + Rails
Category Open Source Software
Type Web Application Framework