glass-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.
Files changed (45) hide show
  1. data/.DS_Store +0 -0
  2. data/.gitignore +19 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +172 -0
  6. data/Rakefile +1 -0
  7. data/glass-rails.gemspec +33 -0
  8. data/lib/.DS_Store +0 -0
  9. data/lib/generators/.DS_Store +0 -0
  10. data/lib/generators/glass.rb +22 -0
  11. data/lib/generators/glass/.DS_Store +0 -0
  12. data/lib/generators/glass/install/install_generator.rb +38 -0
  13. data/lib/generators/glass/install/templates/glass_timeline_item_migration.rb +21 -0
  14. data/lib/generators/glass/install/templates/google-oauth.yml +15 -0
  15. data/lib/generators/glass/install/templates/google_account.rb +28 -0
  16. data/lib/generators/glass/install/templates/initializer.rb +24 -0
  17. data/lib/generators/glass/install/templates/notifications_controller.rb +7 -0
  18. data/lib/generators/glass/model/model_generator.rb +19 -0
  19. data/lib/generators/glass/model/templates/model.rb +28 -0
  20. data/lib/generators/glass/templates/.DS_Store +0 -0
  21. data/lib/generators/glass/templates/templates/image_full.html.erb +9 -0
  22. data/lib/generators/glass/templates/templates/image_left_with_section_right.html.erb +8 -0
  23. data/lib/generators/glass/templates/templates/image_left_with_table_right.html.erb +11 -0
  24. data/lib/generators/glass/templates/templates/list.html.erb +7 -0
  25. data/lib/generators/glass/templates/templates/simple.html.erb +7 -0
  26. data/lib/generators/glass/templates/templates/table.html.erb +8 -0
  27. data/lib/generators/glass/templates/templates/two_column.html.erb +12 -0
  28. data/lib/generators/glass/templates/templates/two_column_with_emphasis_left.html.erb +14 -0
  29. data/lib/generators/glass/templates/templates_generator.rb +16 -0
  30. data/lib/glass-rails.rb +7 -0
  31. data/lib/glass.rb +24 -0
  32. data/lib/glass/.DS_Store +0 -0
  33. data/lib/glass/api_keys.rb +29 -0
  34. data/lib/glass/client.rb +95 -0
  35. data/lib/glass/engine.rb +5 -0
  36. data/lib/glass/menu_item.rb +33 -0
  37. data/lib/glass/rails/version.rb +5 -0
  38. data/lib/glass/subscription.rb +46 -0
  39. data/lib/glass/subscription_notification.rb +75 -0
  40. data/lib/glass/template.rb +45 -0
  41. data/lib/glass/timeline_item.rb +259 -0
  42. data/spec/models/glass/template_spec.rb +12 -0
  43. data/spec/models/glass/timeline_item_spec.rb +9 -0
  44. data/spec/spec_helper.rb +55 -0
  45. metadata +226 -0
data/.DS_Store ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .rvmrc
5
+ .config
6
+ .yardoc
7
+ .rspec
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in glass-rails.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Thirst Labs, Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # Glass::Rails
2
+
3
+ A DSL for building Google Glass apps using Ruby on Rails.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'glass-rails'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install locally by running the following command:
16
+
17
+ $ gem install glass-rails
18
+
19
+ ## Usage
20
+
21
+ ### Setting up
22
+
23
+ We have a rails generator which will generate a
24
+ yaml file for your google api keys. The command for
25
+ the generator is:
26
+
27
+ rails g glass:install
28
+
29
+ This will generate a yaml file for your keys, an initializer for
30
+ setting up configuration details, and migrations for the appropriate
31
+ tables.
32
+
33
+ ### Templates
34
+
35
+ This gem includes a template generator, which provides a basic
36
+ set of default templates (derived directly from the recommended templates
37
+ which are shown in the glass playground).
38
+
39
+ To generate the default templates, you can run the command:
40
+
41
+ rails g glass:templates
42
+
43
+ This will generate a basic series of templates under the path,
44
+ `app/views/glass` though you may want to organize them more logically,
45
+ depending on your use case
46
+
47
+ ### Glass Models - (Introduction)
48
+
49
+ This gem also provides a glass model generator, which generates a timeline-item
50
+ model for your use:
51
+
52
+ For example, let's say you want to post a tweet to a user's glass timeline,
53
+ you may want to have a glass model which represents tweets. To generate that
54
+ model, you can run this command:
55
+
56
+ rails g glass:model tweet
57
+
58
+ and you will find a model generated for you in the directory,
59
+ `app/models/glass/<glassmodelname>.rb`.
60
+
61
+ It is primarly with Glass Models that you generate your glass application,
62
+ so understanding the mechanisms by which we map out over the actual google
63
+ api is probably a good idea.
64
+
65
+ If you want your timeline item to have a list of menu-items, you can specify
66
+ the menu-items in your glass model like so:
67
+
68
+ ```ruby
69
+ class Glass::Tweet < Glass::TimelineItem
70
+ has_menu_item :custom_action_name,
71
+ display_name: "this is displayed",
72
+ icon_url: "http://icons.iconarchive.com/icons/enhancedlabs/lha-objects/128/Filetype-URL-icon.png",
73
+ handles_with: :custom_action_handler
74
+ end
75
+ ```
76
+ ### Glass Models - Menu Items
77
+
78
+ You can define a series of menu items for a glass model,
79
+ using the helper method `has_menu_item`. This method takes the
80
+ following arguments:
81
+
82
+ ```ruby
83
+ class Glass::ExampleCard < Glass::TimelineItem
84
+ has_menu_item <symbolized_name_of_action>, <options>
85
+ ## here options is a hash, and you can define here:
86
+ ## the displayed name of the action/menu item,
87
+ ## i.e. 'like', as well as a url for an icon, and
88
+ ## a callback method which gets executed when you
89
+ ## are notified of an event.
90
+ end
91
+ ```
92
+
93
+ Basically, the way that the google mirror api works, you
94
+ are required to subscribe to notifications from a user to
95
+ get updated on the status of a user action on a timeline
96
+ item. This gems aims to aid the subscription and notification
97
+ process, primarily to get the process bootstrapped and ready to
98
+ go.
99
+
100
+ You will automatically be subscribed to notifications on a timeline
101
+ item, and will get notified to your glass callback url, which we have
102
+ inserted into your routes for you if you have used the install
103
+ generator.
104
+
105
+ Once you have generated a timeline item glass model:
106
+
107
+ ```ruby
108
+ class Glass::Tweet < Glass::TimelineItem
109
+ end
110
+ ```
111
+
112
+ You can use the `has_menu_item` helper method in your
113
+ glass model to define menu items. These menu items will them be
114
+ applied uniformly for your entire class.
115
+
116
+ Once you've posted to the timeline item to the glass user's
117
+ timeline, you are registered to listen for notifications
118
+ that the user has acted on your card. You can specify a callback method
119
+ using the `has_menu_item` helper method, by passing in the
120
+
121
+
122
+
123
+ ### Glass Models - (Posting Content)
124
+
125
+ So using our Glass::Tweet class which we created above, we
126
+ could instantiate a new instance of the class and assign it
127
+ an associated google account like so
128
+
129
+ ```ruby
130
+ gt = Glass::Tweet.new(google_account_id: GoogleAccount.first)
131
+ ```
132
+ Then, you can populate an erb template with instance variables by
133
+ using the `serialize` method which is available to all subclasses
134
+ of Glass::TimelineItem (and yeah, to be clear, this includes Glass::Tweet).
135
+ For example, let's say you have the following erb template:
136
+
137
+ ```erb
138
+ <article>
139
+ <h1><%= @title %></h1>
140
+ <section>
141
+ <ul>
142
+ <%= @content %>
143
+ </ul>
144
+ </section>
145
+ </article>
146
+ ```
147
+
148
+ You can serialize the template for a glass::tweet instance like so:
149
+
150
+ ```ruby
151
+ gt = Glass::Tweet.new(google_account_id: GoogleAccount.first)
152
+ gt.serialize({template_variables: {content: "asdfasdfasdf", title: "title"}})
153
+ ```
154
+
155
+ which will basically populate the `@content` and `@title` instance variables
156
+ in the erb template, render it as a string, and get it prepped to send to the
157
+ mirror api for insertion into the timeline.
158
+
159
+ Then all you have to do is use the following command to actually insert the content:
160
+
161
+ ```ruby
162
+ gt.client.insert
163
+ ```
164
+
165
+
166
+ ## Contributing
167
+
168
+ 1. Fork it
169
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
170
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
171
+ 4. Push to the branch (`git push origin my-new-feature`)
172
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'glass/rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "glass-rails"
8
+ spec.version = Glass::Rails::VERSION
9
+ spec.authors = ["Kunal Modi", "Han Kang"]
10
+ spec.email = ["kunal@thirstlabs.com", 'han@therubyists.org']
11
+ spec.description = %q{ A framework for creating google glass applications using ruby on rails. }
12
+ spec.summary = %q{ A framework for creating google glass applications using ruby on rails.
13
+ This probably isn't for everyone, but we did our best to make it suitable for
14
+ as many cases as possible. }
15
+ spec.homepage = ""
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files`.split($/)
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+
24
+ spec.add_dependency "railties", [">= 3.1"]
25
+ spec.add_dependency "google-api-client"
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "pry"
29
+ spec.add_development_dependency "pry-rails"
30
+ spec.add_development_dependency "rspec", ">= 1.5.2"
31
+ spec.add_development_dependency "rspec-rails", '~> 2.11.0'
32
+
33
+ end
data/lib/.DS_Store ADDED
Binary file
Binary file
@@ -0,0 +1,22 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Glass
4
+ module Generators
5
+ class Base < Rails::Generators::Base #:nodoc:
6
+ def self.source_root
7
+ @_glass_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'glass', generator_name, 'templates'))
8
+ end
9
+
10
+ def self.banner
11
+ "rails generate glass:#{generator_name} #{self.arguments.map{ |a| a.usage }.join(' ')} [options]"
12
+ end
13
+
14
+ private
15
+
16
+ def print_usage
17
+ self.class.help(Thor::Base.shell.new)
18
+ exit
19
+ end
20
+ end
21
+ end
22
+ end
Binary file
@@ -0,0 +1,38 @@
1
+ require 'generators/glass'
2
+ require 'rails/generators'
3
+ require 'rails/generators/migration'
4
+
5
+ module Glass
6
+ module Generators
7
+ class InstallGenerator < Base
8
+ include Rails::Generators::Migration
9
+ argument :user_model, type: :string, default: "User"
10
+
11
+ def create_configuration_file
12
+ copy_file("google-oauth.yml", "config/google-api-keys.yml")
13
+ end
14
+
15
+ def create_glass_account_migration
16
+ generate("model", "google_account token refresh_token expires_at:integer email name id_token verification_secret #{user_model.underscore.singularize}:references")
17
+ remove_file("app/models/google_account.rb")
18
+ template("google_account.rb", "app/models/google_account.rb")
19
+ insert_into_file("app/models/#{user_model.underscore.singularize}.rb", "\n\s\shas_one :google_account\n\n", after: "ActiveRecord::Base\n")
20
+ end
21
+ def self.next_migration_number(path)
22
+ (Time.now.utc.strftime("%Y%m%d%H%M%S").to_i + 1).to_s
23
+ end
24
+ def create_timeline_items_migration
25
+ migration_template "glass_timeline_item_migration.rb", "db/migrate/create_glass_timeline_items.rb"
26
+ end
27
+ def create_subscription_notifications_controller
28
+ generate("controller", "glass/notifications")
29
+ remove_file("app/controllers/glass/notifications_controller.rb")
30
+ template("notifications_controller.rb", "app/controllers/glass/notifications_controller.rb")
31
+ insert_into_file("config/routes.rb", "\n\s\spost 'glass/notifications', to: 'glass/notifications#callback', as: 'glass_notifications_callback'\n\n", after: "routes.draw\sdo\n")
32
+ end
33
+ def create_initializer
34
+ copy_file "initializer.rb", "config/initializers/glass.rb"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ class CreateGlassTimelineItems < ActiveRecord::Migration
2
+ def change
3
+ create_table :glass_timeline_items do |t|
4
+ t.string :type
5
+ t.references :google_account
6
+ t.string :glass_item_id
7
+ t.boolean :is_deleted
8
+ t.string :glass_etag
9
+ t.string :glass_self_link
10
+ t.string :glass_kind
11
+ t.datetime :glass_created_at
12
+ t.datetime :glass_updated_at
13
+ t.string :glass_content_type
14
+ t.text :glass_content
15
+ t.datetime :display_time
16
+
17
+ t.timestamps
18
+ end
19
+ add_index :glass_timeline_items, :google_account_id
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ google_defaults: &google_defaults
2
+ scopes: [userinfo.email, userinfo.profile]
3
+ glass_scopes: [userinfo.email, userinfo.profile, glass.timeline]
4
+ development:
5
+ client_id: CLIENT_ID
6
+ client_secret: CLIENT_SECRET
7
+ <<: *google_defaults
8
+ test:
9
+ client_id: CLIENT_ID
10
+ client_secret: CLIENT_SECRET
11
+ <<: *google_defaults
12
+ production:
13
+ client_id: CLIENT_ID
14
+ client_secret: CLIENT_SECRET
15
+ <<: *google_defaults
@@ -0,0 +1,28 @@
1
+ class GoogleAccount < ActiveRecord::Base
2
+ belongs_to :<%= user_model.underscore.singularize %>
3
+ attr_accessible :email, :expires_at, :name, :refresh_token, :token, :verification_secret
4
+ before_create :generate_verification_secret
5
+ after_create :subscribe_to_google_notifications
6
+ def token_expiry
7
+ Time.at(self.expires_at)
8
+ end
9
+ def has_expired_token?
10
+ token_expiry < Time.now
11
+ end
12
+ def update_google_tokens(google_auth_hash)
13
+ [:token, :id_token, :expires_at].each do |attribute|
14
+ self.send("#{attribute}=", google_auth_hash[attribute.to_s])
15
+ end
16
+ self.save
17
+ end
18
+
19
+ def subscribe_to_google_notifications
20
+ subscription = Glass::Subscription.new google_account: self
21
+ subscription.insert
22
+ end
23
+
24
+ private
25
+ def generate_verification_secret
26
+ self.verification_secret = SecureRandom.urlsafe_base64
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ if Rails.env.development?
2
+ ##
3
+ ## if you've set this elsewhere you may want
4
+ ## to comment this out.
5
+ ##
6
+ ## Glass requires this to be defined for callback url
7
+ ## purposes.
8
+ ##
9
+ Rails.application.routes.default_url_options[:host] = 'localhost:3000'
10
+ elsif Rails.env.test?
11
+
12
+ ## setup whatever you want for default url options for your test env.
13
+ end
14
+
15
+ Glass.setup do |config|
16
+ ## you can override the logo here
17
+ ## config.brandname = "examplename"
18
+
19
+
20
+
21
+ ## manually override your glass views path here.
22
+ config.glass_template_path = "app/views/glass"
23
+
24
+ end
@@ -0,0 +1,7 @@
1
+ class Glass::NotificationsController < ApplicationController
2
+ skip_before_filter :verify_authenticity_token
3
+ def callback
4
+ Glass::SubscriptionNotification.create(params)
5
+ render json: {success: true}
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ require 'generators/glass'
2
+ require 'rails/generators'
3
+ require 'rails/generators/migration'
4
+
5
+ module Glass
6
+ module Generators
7
+ class ModelGenerator < Base
8
+ argument :model_name, type: :string
9
+ def copy_glass_templates
10
+ unless File.directory?("app/models/glass/")
11
+ empty_directory("app/models/glass")
12
+ end
13
+ end
14
+ def create_glass_model
15
+ template("model.rb", "app/models/glass/#{model_name.underscore}.rb")
16
+ end
17
+ end
18
+ end
19
+ end