ng_on_rails 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 112566d25c565d9a8f6354967833d96c630284f4
4
+ data.tar.gz: 509e0df4fb071e2fbdae781ba2f255ae266b33f4
5
+ SHA512:
6
+ metadata.gz: 39650330a0379e048903523177fd690a09275481d715426b67c4c05ddf7bc43d350389c76696a88c22a965753f26f5c67f037e5dfa4672af3d6f09c3e2ab3e8b
7
+ data.tar.gz: 16f22ef0f8319ed9c2298f16f82512b6c19931904002764729ee21471a6c9d192cab13c42371f82d67c5ef759ad2173f0e65bd9cfccc34f3e75b73dce91d20aa
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,259 @@
1
+ ##### *This project is still in developement and uses MIT-LICENSE.*
2
+
3
+ -----------------------------------------------------------
4
+
5
+ ### NgOnRails
6
+
7
+ *A Rails inspired framework for using AngularJS with Rails*
8
+
9
+ The main motivations behind this gem is to standardize and simplify how AngularJS is integrated in a rails application.
10
+
11
+ I am just getting started but this does function *as-is*. Some things left to do:
12
+ * Write more specs!!!
13
+ * Create generators for controllers/services/(views?)
14
+ * (ViewHelper functions via shared service?)
15
+
16
+ I would love feed back (especially on convention choices) and possibly other contributers. Send me a note!
17
+
18
+ #### Overview
19
+
20
+ As time goes on generators for angular controllers and services (rails-models) will be added, as well as some view helpers and directives. For the time being however the the gem is rather simple.
21
+
22
+ It relies on two pieces of slight magic
23
+
24
+ 1. a "Rails" service that holds all your rails variables. This service automatically turns rails instance variables into json that can be used by Angular. For example the rails instance variable `@pages` will get mapped to `Rails.pages` that can be used by angular
25
+ ```
26
+ <div ng-repeat="page in Rails.pages">...
27
+ ```
28
+ To get this work you simply need to load the rails_service.js.erb partial
29
+ ```html.erb
30
+ <script>
31
+ = render( partial: 'angular_app/rails_service', formats: ['js'], locals: { ng_data: ng_data} )
32
+ </script>
33
+ ```
34
+ "rails_service.js.erb" calls the `locals_to_json` helper method to automatically turn instance variables into json. Here `ng_data` is a local rails variable used to customize how this is converted. This will be discussed in detail [below](#locals_to_json).
35
+ 2. Your angular views(partials) should be placed in app/views/angular_app. This solution is discussed in a handfull of places including [here](http://stackoverflow.com/questions/12116476/rails-static-html-template-files-in-the-asset-pipeline-and-caching-in-developmen), but the key parts are:
36
+ ```ruby
37
+ # routes.rb
38
+ scope :angular_app do
39
+ get ':path.html' => 'ng_on_rails#template', constraints: { path: /.+/ }
40
+ end
41
+
42
+ # ng_on_rails_controller.rb
43
+ def template
44
+ @path = params[:path]
45
+ render template: '/angular_app/' + @path, layout: nil
46
+ end
47
+ ```
48
+ You can then use the angular directive 'render'
49
+ ```javascript
50
+ NgOnRailsApp.directive(
51
+ "render",
52
+ function(){
53
+ return {
54
+ restrict: "AE",
55
+ transclude: true,
56
+ template: function(el,attrs){
57
+ return '<div ng_include="\'/angular_app/'+attrs.url+'.html\'"></div>'
58
+ }
59
+ }
60
+ }
61
+ )
62
+ ```
63
+ to load your angualar views in at 'app/views/angular_app'
64
+
65
+ #### Conventions
66
+
67
+ * Put Angular controllers/directives/... in a folder "angular\_app" in the assets directory. Similarly, as discussed above, the angular views(partials) are placed in a folder "angular\_app" in the views directory
68
+ ```
69
+ |-- app/
70
+ |-- assests/
71
+ |-- javascripts/
72
+ |-- angular_app/
73
+ |-- controllers/
74
+ |-- directives/
75
+ |-- services/
76
+ |- app.js
77
+ |-- views/
78
+ |-- angular_app/
79
+
80
+ ```
81
+ Files should be named/put in folders in the same maner that you would in Rails. For instance, if you have a Page model, you would have a pages_controller.js and a service page.js. Then under views you would have pages/{show.html,index.html,...}. *The way these views are handled makes them more like partials that views but for now at least I am not prefixing the name with and underscore "\_"*
82
+
83
+ * As for views, I try to have as little AngularJS outside of my angular_app folder. I will load the "Rails" service and set `ng-app="NgOnRailsApp"` in the application layout. Additionally I will usuallly have an angular `AppController` that is very limited in behavior that is part of the application layout. Again assuming I have a "Page" model I will handle the views like this
84
+
85
+ ```html
86
+ # app/views/pages/index.html
87
+ <!-- Apart from this render directive don't put any other angular in this file -->
88
+ <div render="true" url="pages/index" ng-init="pages=ctrl.rails.pages"></div>
89
+
90
+
91
+ # app/views/angular_app/pages/show.html
92
+ <div ng_controller="PagesController as ctrl">
93
+ <div ng-repeat="page in pages">
94
+ <div ng-show="ctrl.is_editing(page)">...
95
+ ```
96
+ *In the above, `ctrl.rails` has been set to the Rails service in the AppController*
97
+
98
+ * This brings up another point. Use the Controller-As syntax! I know there are people who aren't a fan. However in most apps where I am using angular there is a complicated Model structure. I necessarly want to edit all these things on a single page, though spread out through many partials. Controller-As really really helps keep the logic clear.
99
+
100
+
101
+ #### Angular Services for Rails Models
102
+ You are going to have a service for each rails model. I plan on adding generators but for now this is what my services look like
103
+
104
+ ```coffeescript
105
+ # app/assets/javascripts/angular_app/services/page.js.coffee
106
+ NgOnRailsApp.factory "Page", ($resource) ->
107
+ PageResource = $resource "/survey_link/questions/:id.json", {id: "@id"}, {
108
+ update:{method: "PUT"}
109
+ }
110
+ class Page extends PageResource
111
+ # place class and instance methods here if you want them.
112
+ ```
113
+
114
+
115
+ #### Angular Controllers for Rails Models
116
+ Simalarly you are going to have an angular controller for each rails model. Again, I plan on adding generators but for now an example is below. Note that I place all the REST methods in a rest object. Bridge is a service I use to pass data from one controller to another.
117
+
118
+ ```coffeescript
119
+ NgOnRailsApp.controller 'PagesController', ($scope,Page,Bridge) ->
120
+ # setup
121
+ ctrl = this
122
+ ctrl.bridge = Bridge
123
+ ctrl.data = {}
124
+
125
+ # initializers
126
+ ctrl.setPage = (page)->
127
+ ctrl.bridge.data.page = page
128
+ ctrl.setPages = (pages)->
129
+ ctrl.bridge.data.pages = pages
130
+
131
+ # rest methods
132
+ ctrl.rest =
133
+ index: ->
134
+ params = {}
135
+ Page.query(params).$promise.then (pages) ->
136
+ ctrl.bridge.data.pages = pages
137
+
138
+ show: (page_id)->
139
+ Page.get({id: page_id}).$promise.then (page) ->
140
+ ctrl.bridge.data.page = page
141
+ ctrl.bridge.data.page_versions = page.page_versions
142
+
143
+ new: (doc_id)->
144
+ ctrl.clear()
145
+ ctrl.data.activePage = {}
146
+ ctrl.data.activePage.doc_id = doc_id
147
+ ctrl.data.creating_new_page = true
148
+
149
+ create: ->
150
+ if !(ctrl.locked || ctrl.page_form.$error.required)
151
+ ctrl.locked = true
152
+ working_page = angular.copy(ctrl.data.activePage)
153
+ Page.save(
154
+ working_page,
155
+ (page)->
156
+ ctrl.bridge.data.pages ||= []
157
+ ctrl.bridge.data.pages.push(page)
158
+ ctrl.clear()
159
+ ctrl.locked = false
160
+ ,
161
+ (error)->
162
+ console.log("create_error:",error)
163
+ ctrl.clear()
164
+ ctrl.locked = false
165
+ )
166
+
167
+ edit: (page,doc_id) ->
168
+ ctrl.clear()
169
+ page.show_details = false
170
+ ctrl.data.activePage = page
171
+ ctrl.data.activePage.doc_id = doc_id
172
+ ctrl.data.editing_page = true
173
+
174
+ update: (page)->
175
+ if !(ctrl.locked || ctrl.page_form.$error.required)
176
+ ctrl.locked = true
177
+ page = ctrl.data.activePage unless !!page
178
+ working_page = angular.extend(angular.copy(page),ctrl.data.activePage)
179
+ Page.update(
180
+ working_page,
181
+ (page)->
182
+ # success handler
183
+ ctrl.locked = false
184
+ ,
185
+ (error)->
186
+ console.log("update_error:",error)
187
+ ctrl.locked = false
188
+ )
189
+ ctrl.clear()
190
+
191
+ delete: (index,page,pages)->
192
+ Page.delete(
193
+ page,
194
+ (page)->
195
+ pages ||= ctrl.bridge.data.pages
196
+ pages.splice(index,1)
197
+ ,
198
+ (error)->
199
+ console.log("delete_error:",error)
200
+ )
201
+ ctrl.clear()
202
+
203
+
204
+ # scope methods
205
+ ctrl.toggleDetails = (page)->
206
+ page.show_details = !page.show_details
207
+
208
+ ctrl.resort = (pages) ->
209
+ for page, index in pages
210
+ page.order_index = index + 1
211
+ Page.update(
212
+ page,
213
+ (page)->
214
+ # success handler
215
+ ,
216
+ (error)->
217
+ console.log("update_error:",error)
218
+ )
219
+
220
+ ctrl.clear = ->
221
+ ctrl.data.activePage = null
222
+ ctrl.data.creating_new_page = false
223
+ ctrl.data.editing_page = false
224
+
225
+ ctrl.is_editing = (page)->
226
+ (ctrl.data.editing_page && !!page && page.id == ctrl.data.activePage.id) ||
227
+ (ctrl.data.creating_new_page && !page)
228
+
229
+ # private methods
230
+ some_private_method = ->
231
+ console.log('nobody knows i exist')
232
+
233
+ return
234
+ ```
235
+ <a name="locals_to_json"></a>
236
+ #### Rails variables to Angular-able json.
237
+
238
+ As mentioned using the Rails-service you can get access to all your rails variables in angular.
239
+ ```html.erb
240
+ <script>
241
+ = render( partial: 'angular_app/rails_service', formats: ['js'], locals: { ng_data: ng_data} )
242
+ </script>
243
+ ```
244
+ Here, ng_data is a local rails variable that tells you have to do the conversion:
245
+
246
+ * if ng_data is nil all varibles will be converted with `.to_json` ( or if its a string/numeric with .to_s )
247
+ * if `ng_data['BUILD'].blank?` the default will be to use `.to_json` for conversion.
248
+ * if `ng_data['BUILD']=true` the default will be to look for a `.json` file in the app/views directory. It will guess the name and path to this file using the name of var. For instance, if we have @page it will look for the the file app/views/pages/page.json.
249
+ * if `ng_data[var_name].blank?` the conversion will use the defaults discussed above
250
+ * if `ng_data[var_name]={ path: 'path/to/file', as: model_name } it will use this info to try and find the build file. For instance, suppose I have a collection of pages called `@admin_pages`. Then `ng_data['admin_pages'] = { path: "survey_link/pages/pages", as: :pages }` will look for the file app/views/pages/pages.json seting the local variable `pages = @admin_pages`.
251
+
252
+ To understand it better look at [ng_on_rails_helper.rb](https://github.com/brookisme/ng_on_rails/blob/master/app/helpers/ng_on_rails_helper.rb).
253
+
254
+
255
+
256
+
257
+
258
+
259
+
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'NgOnRails'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+ Bundler::GemHelper.install_tasks
21
+
@@ -0,0 +1,3 @@
1
+ if (!window.NgOnRailsApp){
2
+ window.NgOnRailsApp = angular.module("NgOnRailsApp", ["ngResource","ngAnimate","ngSanitize"])
3
+ }
@@ -0,0 +1,12 @@
1
+ NgOnRailsApp.directive(
2
+ "render",
3
+ function(){
4
+ return {
5
+ restrict: "AE",
6
+ transclude: true,
7
+ template: function(el,attrs){
8
+ return '<div ng_include="\'/angular_app/'+attrs.url+'.html\'"></div>'
9
+ }
10
+ }
11
+ }
12
+ )
@@ -0,0 +1,3 @@
1
+ //
2
+ //= require_tree .
3
+ //
@@ -0,0 +1,6 @@
1
+ class NgOnRailsController < ApplicationController
2
+ def template
3
+ @path = params[:path]
4
+ render template: '/angular_app/' + @path, layout: nil
5
+ end
6
+ end
@@ -0,0 +1,77 @@
1
+ module NgOnRailsHelper
2
+ def locals_to_json ng_data
3
+ j = ActiveSupport::JSON
4
+ locals_hash = {}
5
+ instance_variable_names.each do |var_name|
6
+ unless !!var_name.match(/^@_/)
7
+ unless ignorables.include? var_name
8
+ name = var_name.gsub("@","")
9
+ instance_var = instance_variable_get(var_name)
10
+ unless instance_var.blank?
11
+ if ng_data.blank?
12
+ rv = instance_var
13
+ else
14
+ unless ng_data[name] == "IGNORE"
15
+ if !ng_data[name]
16
+ if !!ng_data["BUILD"]
17
+ rv = build(name,instance_var)
18
+ else
19
+ rv = instance_var
20
+ end
21
+ elsif ng_data[name]=="BUILD"
22
+ rv = build(name,instance_var)
23
+ elsif ng_data[name].class==Hash
24
+ path = ng_data[name][:path]
25
+ model_name = ng_data[name][:as] || name
26
+ rv = build(model_name,instance_var,path)
27
+ end
28
+ end
29
+ end
30
+ unless !defined?(rv) || rv.blank?
31
+ if (rv.is_a?(String) && !is_json?(rv)) || rv.is_a?(Numeric)
32
+ locals_hash[name] = rv
33
+ elsif is_json?(rv)
34
+ locals_hash[name] = j.decode(rv)
35
+ else
36
+ locals_hash[name] = j.decode(rv.to_json)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ return locals_hash.to_json
44
+ end
45
+
46
+ private
47
+
48
+ def ignorables
49
+ [
50
+ "@view_renderer",
51
+ "@view_flow",
52
+ "@output_buffer",
53
+ "@virtual_path",
54
+ "@fixture_connections",
55
+ "@example",
56
+ "@fixture_cache",
57
+ "@loaded_fixtures",
58
+ "@controller",
59
+ "@request",
60
+ "@output_buffer",
61
+ "@rendered"
62
+ ]
63
+ end
64
+
65
+ def is_json? string
66
+ begin
67
+ !!JSON.parse(string)
68
+ rescue
69
+ false
70
+ end
71
+ end
72
+
73
+ def build name, var, path=nil
74
+ path = name unless !!path
75
+ render(path.to_s+'.json', name.to_sym => var)
76
+ end
77
+ end
@@ -0,0 +1,3 @@
1
+ NgOnRailsApp.service('Rails', function(){
2
+ return JSON.parse('<%= raw(locals_to_json(ng_data)) %>')
3
+ });
data/config/routes.rb ADDED
@@ -0,0 +1,6 @@
1
+ Rails.application.routes.draw do
2
+ # AngularJS Templates
3
+ scope :angular_app do
4
+ get ':path.html' => 'ng_on_rails#template', constraints: { path: /.+/ }
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ require "ng_on_rails/engine"
2
+ module NgOnRails
3
+ end
@@ -0,0 +1,11 @@
1
+ module NgOnRails
2
+ class Engine < ::Rails::Engine
3
+ initializer 'ng_on_rails.load_static_assets' do |app|
4
+ app.middleware.use ::ActionDispatch::Static, "#{root}/app"
5
+ end
6
+
7
+ initializer "ng_on_rails.view_helpers" do
8
+ ActionView::Base.send :include, NgOnRailsHelper
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module NgOnRails
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :ng_on_rails do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ng_on_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Brookie Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.1.6
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.1.6
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A Rails inspired framework for using AngularJS with Rails
56
+ email:
57
+ - brookwilliams@laborvoices.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - MIT-LICENSE
63
+ - README.md
64
+ - Rakefile
65
+ - app/assets/javascripts/app.js
66
+ - app/assets/javascripts/directives/shared.js.erb
67
+ - app/assets/javascripts/ng_on_rails.js
68
+ - app/controllers/ng_on_rails_controller.rb
69
+ - app/helpers/ng_on_rails_helper.rb
70
+ - app/views/angular_app/_rails_service.js.erb
71
+ - config/routes.rb
72
+ - lib/ng_on_rails.rb
73
+ - lib/ng_on_rails/engine.rb
74
+ - lib/ng_on_rails/version.rb
75
+ - lib/tasks/ng_on_rails_tasks.rake
76
+ homepage: http://www.laborvoices.com
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.2.2
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: A Rails inspired framework for using AngularJS with Rails
100
+ test_files: []