glass-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,45 @@
1
+ require "rails/all"
2
+ require 'action_view'
3
+ module Glass
4
+ class Template < ActionView::Base
5
+ attr_accessor :timeline_item, :template_name
6
+
7
+ ## basically, any thing passed in the hash here gets instantiated as
8
+ ## an instance variable in the view, except :template_name
9
+ ##
10
+ ## the [:template_name] key will be reserved for specifying the relative
11
+ ## path (to the glass_template_path) to your template.
12
+
13
+ ## For example,
14
+
15
+ ## if your glass_template_path is set to:
16
+ ## "app/views/glass-templates"
17
+
18
+ ## and you have a file in a folder
19
+ ## "app/views/glass-templates/tweets/blue.html.erb"
20
+
21
+ ## then your template name would be:
22
+ ## "tweets/blue.html.erb"
23
+ def initialize(opts={})
24
+ self.template_name = opts.delete(:template_name) || "simple.html.erb"
25
+ set_template_instance_variables(opts)
26
+ super(glass_template_path)
27
+ end
28
+ def render_self
29
+ self.render template: self.template_name
30
+ end
31
+ private
32
+
33
+ ##
34
+ ## substantiate the instance variables needed by action view for rendering
35
+ ## in the erb templates.
36
+ ##
37
+ def set_template_instance_variables(opts)
38
+ opts.each {|k,v| self.instance_variable_set("@#{k}", v) }
39
+ end
40
+ ## just for convenience.
41
+ def glass_template_path
42
+ ::Glass.glass_template_path
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,259 @@
1
+ require 'active_record'
2
+ require "glass/menu_item"
3
+ ## this is an abstract class, not intended to be
4
+ ## used directly
5
+
6
+ module Glass
7
+ class TimelineItem < ::ActiveRecord::Base
8
+ class GoogleAccountNotSpecifiedError < StandardError;end;
9
+ class UnserializedTemplateError < StandardError; end;
10
+ class MenuItemHandlerIsNotDefinedError < StandardError; end;
11
+ class TimelineInsertionError < StandardError; end;
12
+
13
+ self.table_name = :glass_timeline_items
14
+
15
+ belongs_to :google_account
16
+
17
+ attr_accessible :display_time, :glass_content, :glass_content_type,
18
+ :glass_created_at, :glass_etag, :glass_item_id,
19
+ :glass_kind, :glass_self_link, :glass_updated_at,
20
+ :is_deleted, :google_account_id
21
+
22
+
23
+
24
+ ## i'd use cattr_accessor, but unfortunately
25
+ ## ruby has some very crappy class variables, which
26
+ ## are nonsensically over-written across sub-classes.
27
+ ## so use the rails class_attribute helpers instead.
28
+
29
+ class_attribute :actions
30
+ class_attribute :menu_items
31
+ class_attribute :default_template
32
+
33
+ attr_accessor :template_type, :to_json
34
+
35
+
36
+
37
+ ## only a writer for these two
38
+ ## because I want to hook an error
39
+ ## message to each of these if they haven't
40
+ ## had there values set yet.
41
+ attr_writer :client, :mirror_content, :template_name
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+ ### a couple custom attr_readers which raise a
51
+ ### helpful error message if the value is nil;
52
+ ### i.e. error flow handling.
53
+ def mirror_content
54
+ raise UnserializedTemplateError unless @mirror_content
55
+ @mirror_content
56
+ end
57
+ def client
58
+ raise UnserializedTemplateError unless @client
59
+ @client
60
+ end
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+ ## this methods sets the default template for
71
+ ## all instances of the class.
72
+
73
+ ## Usage:
74
+ ## class Glass::Tweet < Glass::TimelineItem
75
+
76
+ ## defaults_template "table.html.erb"
77
+ ## this defaults to the glass_template_path
78
+ ## which you set in your glass initializer.
79
+
80
+ ## end
81
+ def self.defaults_template(opts={})
82
+ self.default_template = opts[:with] if opts[:with]
83
+ end
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+ ## this methods sets the default template for
93
+ ## all instances of the class.
94
+
95
+ ## Usage:
96
+ ## class Glass::Tweet < Glass::TimelineItem
97
+
98
+ ## manages_templates :template_manager_name
99
+ ## this will set your template manager
100
+ ## for this class. this will override
101
+ ## defaults_template path if it is
102
+ ## defined.
103
+
104
+ ## end
105
+ def self.manages_templates(opts={})
106
+ self.template_manager = opts[:with] if opts[:with]
107
+ end
108
+
109
+
110
+
111
+
112
+
113
+ ## this methods sets the default template for
114
+ ## all instances of the class.
115
+
116
+ ## Usage:
117
+ ## class Glass::Tweet < Glass::TimelineItem
118
+
119
+ ## has_menu_item :my_custom_action,
120
+ ## display_name: "Displayed Name",
121
+ ## icon_url: "url for icon",
122
+ ## handles_with: :custom_handler_methodname
123
+
124
+ ## def custom_handler_methodname
125
+ ## # this gets executed when this
126
+ ## # action occurs.
127
+ ## end
128
+ ## end
129
+ def self.has_menu_item(action_sym, opts={})
130
+ self.actions ||= []
131
+ self.menu_items ||= []
132
+ unless self.actions.include?(action_sym)
133
+ self.actions += [action_sym]
134
+ defines_callback_methods(action_sym, opts)
135
+ menu_item = ::Glass::MenuItem.create(action_sym, opts)
136
+ self.menu_items += [menu_item]
137
+ end
138
+ end
139
+
140
+
141
+
142
+ ## this is really just a little meta-programming
143
+ ## trick which basically forces a call to the method
144
+ ## specified by with parameter in the has_menu_item method.
145
+ ##
146
+ ## it allows you to put the callback logic right
147
+ ## there in the model.
148
+
149
+ def self.defines_callback_methods(action, opts)
150
+ self.send(:define_method, "handles_#{action.to_s.underscore}") do
151
+ if self.respond_to?(opts[:handled_by])
152
+ self.send(opts[:handled_by])
153
+ else
154
+ raise MenuItemHandlerIsNotDefinedError
155
+ end
156
+ end
157
+ end
158
+
159
+
160
+
161
+ ## not meant to be a part of the public api.
162
+ def self.menu_items_hash
163
+ {menuItems: self.menu_items.map(&:serialize) }
164
+ end
165
+
166
+ ## not meant to be a part of the public api.
167
+ def menu_items_hash
168
+ self.class.menu_items_hash
169
+ end
170
+
171
+
172
+
173
+
174
+
175
+ ## this method will instantiate instance variables
176
+ ## in the erb template with the values you specify
177
+ ## in a hash parameter under the key [:template_variables]
178
+
179
+ ## For example,
180
+ ## @google_account = GoogleAccount.first
181
+ ## @timeline_object = TimelineObject.new(google_account_id: @google_account.id)
182
+ ## @timeline_object.serialize({template_variables: {content: "this is the content
183
+ ## i've pushed to glass"}})
184
+ ##
185
+ ## would render this erb template:
186
+
187
+
188
+ ## <article>
189
+ ## <%= @content %>
190
+ ## </article>
191
+
192
+ ## into this:
193
+
194
+ ## '<article> \n this is the content i've pushed to glass \n </article>'
195
+ ##
196
+ ##
197
+ ## an html serialization of your timeline object, which glass
198
+ ## requests you send with your push.
199
+
200
+
201
+ ##
202
+ def serialize(opts={})
203
+ raise GoogleAccountNotSpecifiedError unless self.google_account.present?
204
+ type = self.template_type || :html
205
+ json_hash = {}
206
+ json_hash[type] = self.setup_template(opts.delete(:template_variables).merge({template_name: opts.delete(:template_name) }))
207
+ json_hash = json_hash.merge(self.menu_items_hash)
208
+ json_hash.merge(opts)
209
+ self.to_json = json_hash
210
+ self.client = Glass::Client.create(self)
211
+ return self
212
+ end
213
+
214
+ def insert(opts={})
215
+ result = client.insert(opts)
216
+ if result.error?
217
+ raise TimelineInsertionError
218
+ else
219
+ data = result.data
220
+ result_data_type = :html #default
221
+ [:html, :text].each do |result_type|
222
+ result_data_type = result_type if data.send(result_type).present?
223
+ end
224
+ self.update_attributes(glass_item_id: data.id,
225
+ glass_etag: data.etag,
226
+ glass_self_link: data.self_link,
227
+ glass_kind: data.kind,
228
+ glass_created_at: data.created,
229
+ glass_updated_at: data.updated,
230
+ glass_content_type: result_data_type,
231
+ glass_content: data.send(result_data_type))
232
+ end
233
+ end
234
+ def patch(opts={})
235
+
236
+ end
237
+ # def update(opts={})
238
+
239
+ # end
240
+
241
+
242
+
243
+ ## this is not intended to be a part of the public api
244
+ def template_name
245
+ @template_name = self.class.default_template || "simple.html.erb"
246
+ end
247
+
248
+ ## this is not intended to be a part of the public api
249
+ def setup_template(variables={})
250
+ glass_template_path = variables[:template_name] || self.template_name
251
+ Glass::Template.new({template_name: glass_template_path}.merge(variables)).render_self
252
+ end
253
+
254
+ ## this is not intended to be a part of the public api
255
+ def has_default_template?
256
+ self.class.default_template
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,12 @@
1
+ require "glass"
2
+ require "glass/template"
3
+ describe "Glass::Template" do
4
+ context "HTML" do
5
+ before :each do
6
+ @template = Glass::Template.new
7
+ end
8
+ it "should not convert to an empty string on to_s" do
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ # require "glass/timeline_item"
2
+ describe "Glass::TimelineItem" do
3
+ context "class" do
4
+
5
+ it "should have be able to " do
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,55 @@
1
+ if $LOADED_FEATURES.grep(/spec\/spec_helper\.rb/).any?
2
+ begin
3
+ raise "foo"
4
+ rescue => e
5
+ puts <<-MSG
6
+ ===================================================
7
+ It looks like spec_helper.rb has been loaded
8
+ multiple times. Normalize the require to:
9
+
10
+ require "spec/spec_helper"
11
+
12
+ Things like File.join and File.expand_path will
13
+ cause it to be loaded multiple times.
14
+
15
+ Loaded this time from:
16
+
17
+ #{e.backtrace.join("\n ")}
18
+ ===================================================
19
+ MSG
20
+ end
21
+ end
22
+
23
+ require 'rubygems'
24
+
25
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
26
+ ENV["RAILS_ENV"] ||= 'test'
27
+ require 'rspec'
28
+
29
+ # ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
30
+ # Requires supporting ruby files with custom matchers and macros, etc,
31
+ # in spec/support/ and its subdirectories.
32
+ RSpec.configure do |config|
33
+ # ## Mock FrameworkRSpec.configure do |config|
34
+ # config.include FactoryGirl::Syntax::Methods
35
+
36
+ # #
37
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
38
+ #
39
+ # config.mock_with :mocha
40
+ # config.mock_with :flexmock
41
+ # config.mock_with :rr
42
+
43
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
44
+ # config.fixture_path = "#{::Rails.root}/spec/fixtures"
45
+
46
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
47
+ # examples within a transaction, remove the following line or assign false
48
+ # # instead of true.
49
+ # config.use_transactional_fixtures = true
50
+
51
+ # # If true, the base class of anonymous controllers will be inferred
52
+ # # automatically. This will be the default behavior in future versions of
53
+ # # rspec-rails.
54
+ # config.infer_base_class_for_anonymous_controllers = false
55
+ end
metadata ADDED
@@ -0,0 +1,226 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: glass-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kunal Modi
9
+ - Han Kang
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-05-20 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: railties
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '3.1'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '3.1'
31
+ - !ruby/object:Gem::Dependency
32
+ name: google-api-client
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '1.3'
63
+ - !ruby/object:Gem::Dependency
64
+ name: rake
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: pry
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: pry-rails
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - '>='
117
+ - !ruby/object:Gem::Version
118
+ version: 1.5.2
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - '>='
125
+ - !ruby/object:Gem::Version
126
+ version: 1.5.2
127
+ - !ruby/object:Gem::Dependency
128
+ name: rspec-rails
129
+ requirement: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ~>
133
+ - !ruby/object:Gem::Version
134
+ version: 2.11.0
135
+ type: :development
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ~>
141
+ - !ruby/object:Gem::Version
142
+ version: 2.11.0
143
+ description: ' A framework for creating google glass applications using ruby on rails. '
144
+ email:
145
+ - kunal@thirstlabs.com
146
+ - han@therubyists.org
147
+ executables: []
148
+ extensions: []
149
+ extra_rdoc_files: []
150
+ files:
151
+ - .DS_Store
152
+ - .gitignore
153
+ - .rvmrc
154
+ - Gemfile
155
+ - LICENSE.txt
156
+ - README.md
157
+ - Rakefile
158
+ - glass-rails.gemspec
159
+ - lib/.DS_Store
160
+ - lib/generators/.DS_Store
161
+ - lib/generators/glass.rb
162
+ - lib/generators/glass/.DS_Store
163
+ - lib/generators/glass/install/install_generator.rb
164
+ - lib/generators/glass/install/templates/glass_timeline_item_migration.rb
165
+ - lib/generators/glass/install/templates/google-oauth.yml
166
+ - lib/generators/glass/install/templates/google_account.rb
167
+ - lib/generators/glass/install/templates/initializer.rb
168
+ - lib/generators/glass/install/templates/notifications_controller.rb
169
+ - lib/generators/glass/model/model_generator.rb
170
+ - lib/generators/glass/model/templates/model.rb
171
+ - lib/generators/glass/templates/.DS_Store
172
+ - lib/generators/glass/templates/templates/image_full.html.erb
173
+ - lib/generators/glass/templates/templates/image_left_with_section_right.html.erb
174
+ - lib/generators/glass/templates/templates/image_left_with_table_right.html.erb
175
+ - lib/generators/glass/templates/templates/list.html.erb
176
+ - lib/generators/glass/templates/templates/simple.html.erb
177
+ - lib/generators/glass/templates/templates/table.html.erb
178
+ - lib/generators/glass/templates/templates/two_column.html.erb
179
+ - lib/generators/glass/templates/templates/two_column_with_emphasis_left.html.erb
180
+ - lib/generators/glass/templates/templates_generator.rb
181
+ - lib/glass-rails.rb
182
+ - lib/glass.rb
183
+ - lib/glass/.DS_Store
184
+ - lib/glass/api_keys.rb
185
+ - lib/glass/client.rb
186
+ - lib/glass/engine.rb
187
+ - lib/glass/menu_item.rb
188
+ - lib/glass/rails/version.rb
189
+ - lib/glass/subscription.rb
190
+ - lib/glass/subscription_notification.rb
191
+ - lib/glass/template.rb
192
+ - lib/glass/timeline_item.rb
193
+ - spec/models/glass/template_spec.rb
194
+ - spec/models/glass/timeline_item_spec.rb
195
+ - spec/spec_helper.rb
196
+ homepage: ''
197
+ licenses:
198
+ - MIT
199
+ post_install_message:
200
+ rdoc_options: []
201
+ require_paths:
202
+ - lib
203
+ required_ruby_version: !ruby/object:Gem::Requirement
204
+ none: false
205
+ requirements:
206
+ - - '>='
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ required_rubygems_version: !ruby/object:Gem::Requirement
210
+ none: false
211
+ requirements:
212
+ - - '>='
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ requirements: []
216
+ rubyforge_project:
217
+ rubygems_version: 1.8.25
218
+ signing_key:
219
+ specification_version: 3
220
+ summary: A framework for creating google glass applications using ruby on rails. This
221
+ probably isn't for everyone, but we did our best to make it suitable for as many
222
+ cases as possible.
223
+ test_files:
224
+ - spec/models/glass/template_spec.rb
225
+ - spec/models/glass/timeline_item_spec.rb
226
+ - spec/spec_helper.rb