From 4125ff082a342c469fa9d1a30088a3b30c5bd2e2 Mon Sep 17 00:00:00 2001 From: Akash Manohar J Date: Wed, 7 Mar 2012 20:10:12 +0530 Subject: [PATCH] Basic app to list created channels Signed-off-by: Akash Manohar J --- app/assets/javascripts/application.js | 2 +- .../controllers/channels_controller.js.coffee | 2 + .../ember/models/channel.js.coffee | 2 + .../javascripts/ember/models/user.js.coffee | 7 + .../ember/templates/channels/list.handlebars | 5 + .../ember/templates/channels/show.handlebars | 1 + .../ember/views/channels/list.js.coffee | 7 + .../ember/views/channels/show.js.coffee | 5 + app/assets/javascripts/lib/ember-rest.js | 280 ++++++++++++++++++ app/controllers/main_controller.rb | 3 + app/models/user.rb | 1 + app/views/layouts/application.html.erb | 11 + app/views/main/index.html.erb | 15 +- config/routes.rb | 3 +- 14 files changed, 339 insertions(+), 5 deletions(-) create mode 100644 app/assets/javascripts/ember/controllers/channels_controller.js.coffee create mode 100644 app/assets/javascripts/ember/models/channel.js.coffee create mode 100644 app/assets/javascripts/ember/models/user.js.coffee create mode 100644 app/assets/javascripts/ember/templates/channels/list.handlebars create mode 100644 app/assets/javascripts/ember/templates/channels/show.handlebars create mode 100644 app/assets/javascripts/ember/views/channels/list.js.coffee create mode 100644 app/assets/javascripts/ember/views/channels/show.js.coffee create mode 100644 app/assets/javascripts/lib/ember-rest.js diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index ffc35b4a..b146ee9f 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -13,6 +13,6 @@ //= require jquery //= require jquery_ujs //= require ember-dev -//= require ember +//= require lib/ember-rest.js //= require ember/kandan //= require_tree . diff --git a/app/assets/javascripts/ember/controllers/channels_controller.js.coffee b/app/assets/javascripts/ember/controllers/channels_controller.js.coffee new file mode 100644 index 00000000..da75b14c --- /dev/null +++ b/app/assets/javascripts/ember/controllers/channels_controller.js.coffee @@ -0,0 +1,2 @@ +Kandan.ChannelsController = Ember.ResourceController.create + resourceType: Kandan.Channel diff --git a/app/assets/javascripts/ember/models/channel.js.coffee b/app/assets/javascripts/ember/models/channel.js.coffee new file mode 100644 index 00000000..22fde931 --- /dev/null +++ b/app/assets/javascripts/ember/models/channel.js.coffee @@ -0,0 +1,2 @@ +class Kandan.Channel extends Ember.Resource + resourceUrl: '/channels' diff --git a/app/assets/javascripts/ember/models/user.js.coffee b/app/assets/javascripts/ember/models/user.js.coffee new file mode 100644 index 00000000..eafdcfc7 --- /dev/null +++ b/app/assets/javascripts/ember/models/user.js.coffee @@ -0,0 +1,7 @@ +class Kandan.User extends Ember.Resource + resourceUrl: '/users' + + full_name: Ember.computed( + ()-> + "#{@get('first_name')} #{@get('last_name')}" + ) \ No newline at end of file diff --git a/app/assets/javascripts/ember/templates/channels/list.handlebars b/app/assets/javascripts/ember/templates/channels/list.handlebars new file mode 100644 index 00000000..ddf14833 --- /dev/null +++ b/app/assets/javascripts/ember/templates/channels/list.handlebars @@ -0,0 +1,5 @@ +
+ {{#each channels}} + {{view Kandan.ShowChannelView channelBinding="this"}} + {{/each}} +
\ No newline at end of file diff --git a/app/assets/javascripts/ember/templates/channels/show.handlebars b/app/assets/javascripts/ember/templates/channels/show.handlebars new file mode 100644 index 00000000..2a3fe673 --- /dev/null +++ b/app/assets/javascripts/ember/templates/channels/show.handlebars @@ -0,0 +1 @@ +{{channel.id}}-{{channel.name}} \ No newline at end of file diff --git a/app/assets/javascripts/ember/views/channels/list.js.coffee b/app/assets/javascripts/ember/views/channels/list.js.coffee new file mode 100644 index 00000000..30792da2 --- /dev/null +++ b/app/assets/javascripts/ember/views/channels/list.js.coffee @@ -0,0 +1,7 @@ +Kandan.ListChannelsView = Ember.View.extend({ + templateName: 'ember/templates/channels/list' + channelsBinding: 'Kandan.ChannelsController' + + refreshList: ()-> + Kandan.ChannelsController.findAll() +}) \ No newline at end of file diff --git a/app/assets/javascripts/ember/views/channels/show.js.coffee b/app/assets/javascripts/ember/views/channels/show.js.coffee new file mode 100644 index 00000000..95a43389 --- /dev/null +++ b/app/assets/javascripts/ember/views/channels/show.js.coffee @@ -0,0 +1,5 @@ +Kandan.ShowChannelView = Ember.View.extend({ + templateName: 'ember/templates/channels/show' + className: ['channel-name'] + tagName: 'div' +}) \ No newline at end of file diff --git a/app/assets/javascripts/lib/ember-rest.js b/app/assets/javascripts/lib/ember-rest.js new file mode 100644 index 00000000..c671cde7 --- /dev/null +++ b/app/assets/javascripts/lib/ember-rest.js @@ -0,0 +1,280 @@ +/** + Ember-REST.js + + A simple library for RESTful resources in Ember.js + + Copyright (c) 2012 Cerebris Corporation + + Licensed under the MIT license: + http://www.opensource.org/licenses/mit-license.php +*/ + +/** + A model class for RESTful resources + + Extend this class and define the following properties: + + * `resourceUrl` -- the base url of the resource (e.g. '/contacts'); + will append '/id' for individual resources (required) + * `resourceName` -- the name used to contain the serialized data in this + object's JSON representation (required only for serialization) + * `resourceProperties` -- an array of property names to be returned in this + object's JSON representation (required only for serialization) + + Because `resourceName` and `resourceProperties` are only used for + serialization, they aren't required for read-only resources. + + You may also wish to override / define the following methods: + + * `serialize()` + * `serializeProperty(prop)` + * `deserialize(json)` + * `deserializeProperty(prop, value)` + * `validate()` +*/ +Ember.Resource = Ember.Object.extend({ + resourceUrl: Ember.required(), + + /** + Duplicate properties from another resource + + * `source` -- an Ember.Resource object + * `props` -- the array of properties to be duplicated; + defaults to `resourceProperties` + */ + duplicateProperties: function(source, props) { + var prop; + + if (props === undefined) props = this.resourceProperties; + + for(var i = 0; i < props.length; i++) { + prop = props[i]; + this.set(prop, source.get(prop)); + } + }, + + /** + Generate this resource's JSON representation + + Override this or `serializeProperty` to provide custom serialization + + REQUIRED: `resourceProperties` and `resourceName` (see note above) + */ + serialize: function() { + var name = this.resourceName, + props = this.resourceProperties, + prop, + ret = {}; + + ret[name] = {}; + for(var i = 0; i < props.length; i++) { + prop = props[i]; + ret[name][prop] = this.serializeProperty(prop); + } + return ret; + }, + + /** + Generate an individual property's JSON representation + + Override to provide custom serialization + */ + serializeProperty: function(prop) { + return this.get(prop); + }, + + /** + Set this resource's properties from JSON + + Override this or `deserializeProperty` to provide custom deserialization + */ + deserialize: function(json) { + Ember.beginPropertyChanges(this); + for(var prop in json) { + if (json.hasOwnProperty(prop)) this.deserializeProperty(prop, json[prop]); + } + Ember.endPropertyChanges(this); + return this; + }, + + /** + Set an individual property from its value in JSON + + Override to provide custom serialization + */ + deserializeProperty: function(prop, value) { + this.set(prop, value); + }, + + /** + Load via ajax and deserialize + + REQUIRED: `id` + */ + findResource: function() { + var self = this; + + return jQuery.ajax({ + url: this._resourceUrl(), + dataType: 'json', + type: 'GET' + }).done( function(json) { + self.deserialize(json); + }); + }, + + /** + Create (if new) or update (if existing) record via ajax + + Will call validate() if defined for this record + + If successful, updates this record's id and other properties + by calling `deserialize()` with the data returned. + + REQUIRED: `properties` and `name` (see note above) + */ + saveResource: function() { + var self = this; + + if (this.validate !== undefined) { + var error = this.validate(); + if (error) { + return { + fail: function(f) { f(error); return this; }, + done: function() { return this; }, + always: function(f) { f(); return this; } + }; + } + } + + return jQuery.ajax({ + url: this._resourceUrl(), + data: this.serialize(), + dataType: 'json', + type: (this.isNew() ? 'POST' : 'PUT') + }).done( function(json) { + // Update properties + if (json) + self.deserialize(json); + }); + }, + + /** + Delete resource via ajax + */ + destroyResource: function() { + return jQuery.ajax({ + url: this._resourceUrl(), + dataType: 'json', + type: 'DELETE' + }); + }, + + /** + Is this a new resource? + */ + isNew: function() { + return (this._id() === undefined); + }, + + /** + @private + + The URL for this resource, based on `resourceUrl` and `id` (which will be + undefined for new resources). + */ + _resourceUrl: function() { + var url = this.resourceUrl, + id = this._id(); + + if (id !== undefined) + url += '/' + id; + + return url; + }, + + /** + @private + + The id for this resource. + */ + _id: function() { + return this.get('id'); + } +}); + +/** + A controller for RESTful resources + + Extend this class and define the following: + + * `resourceType` -- an Ember.Resource class; the class must have a `serialize()` method + that returns a JSON representation of the object + * `resourceUrl` -- (optional) the base url of the resource (e.g. '/contacts/active'); + will default to the `resourceUrl` for `resourceType` +*/ +Ember.ResourceController = Ember.ArrayController.extend({ + resourceType: Ember.required(), + + /** + @private + */ + init: function() { + this._super(); + this.clearAll(); + }, + + /** + Create and load a single `Ember.Resource` from JSON + */ + load: function(json) { + var resource = this.get('resourceType').create().deserialize(json); + this.pushObject(resource); + }, + + /** + Create and load `Ember.Resource` objects from a JSON array + */ + loadAll: function(json) { + for (var i=0; i < json.length; i++) + this.load(json[i]); + }, + + /** + Clear this controller's contents (without deleting remote resources) + */ + clearAll: function() { + this.set("content", []); + }, + + /** + Replace this controller's contents with an ajax call to `url` + */ + findAll: function() { + var self = this; + + return jQuery.ajax({ + url: this._resourceUrl(), + dataType: 'json', + type: 'GET' + }).done( function(json) { + self.clearAll(); + self.loadAll(json); + }); + }, + + /** + @private + + Base URL for ajax calls + + Will use the `resourceUrl` set for this controller, or if that's missing, + the `resourceUrl` specified for `resourceType`. + */ + _resourceUrl: function() { + if (this.resourceUrl === undefined) + return this.get('resourceType').prototype.resourceUrl; + else + return this.resourceUrl; + } +}); diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 88181c28..f4a1a103 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -1,4 +1,7 @@ class MainController < ApplicationController + before_filter :authenticate_user! + def index + @channels = Channel.all end end diff --git a/app/models/user.rb b/app/models/user.rb index 8cde1ad1..29f68692 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,7 @@ class User < ActiveRecord::Base has_many :activities + before_save :ensure_authentication_token # Include default devise modules. Others available are: # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 8a2a9672..f0761e9c 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,6 +9,17 @@ <%- end %> <%= javascript_include_tag "application" %> + <%= javascript_tag do %> + <%- if user_signed_in? %> + <%- current_user_data = { + :id => current_user.id, + :name => "#{current_user.first_name} #{current_user.last_name}", + :auth_token => current_user.authentication_token + } + %> + $.data(document, 'current_user', <%= current_user_data.to_json.html_safe %>); + <%- end %> + <%- end %> <%= csrf_meta_tags %> diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index 77a4757a..caa882ba 100644 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -1,2 +1,13 @@ -

Main#index

-

Find me in app/views/main/index.html.erb

+
+ + + + <%= javascript_tag do %> + $(function() { + Kandan.ChannelsController.loadAll(<%= @channels.to_json.html_safe %>); + }); + <%- end %> + +
diff --git a/config/routes.rb b/config/routes.rb index 374d5a84..df846952 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,7 @@ Kandan::Application.routes.draw do root :to => "main#index" - - #devise_for :users + devise_for :users # The priority is based upon order of creation: # first created -> highest priority.