nali 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ require 'nali/extensions'
2
+ require 'nali/application'
3
+ require 'nali/connection'
4
+ require 'nali/controller'
5
+ require 'nali/model'
6
+ require 'nali/helpers'
@@ -0,0 +1,112 @@
1
+ module Nali
2
+
3
+ class Application < Sinatra::Base
4
+
5
+ set :root, File.expand_path( '.' )
6
+ set :database_file, File.join( root, 'config/database.yml' )
7
+ set :assets, Sprockets::Environment.new( root )
8
+ set :assets_digest, false
9
+ set :assets_debug, false
10
+ set :static, true
11
+
12
+ register Sinatra::ActiveRecordExtension
13
+
14
+ configure :development do
15
+ register Sinatra::Reloader
16
+ also_reload File.join( root, '**/*.rb' )
17
+ end
18
+
19
+ require File.join( root, 'config/environments', environment.to_s )
20
+
21
+ configure do
22
+ assets.cache = Sprockets::Cache::FileStore.new File.join( root, 'tmp/cache' )
23
+
24
+ %w( app/templates app/assets/stylesheets app/assets/javascripts lib/assets/stylesheets
25
+ lib/assets/javascripts vendor/assets/stylesheets vendor/assets/javascripts
26
+ ).each { |path| assets.append_path File.join( root, path ) }
27
+
28
+ Sprockets::Helpers.configure do |config|
29
+ config.environment = assets
30
+ config.debug = assets_debug
31
+ config.digest = assets_digest
32
+ end
33
+
34
+ end
35
+
36
+ get '/assets/*.*' do |path, ext|
37
+ pass if ext == 'html' or not asset = settings.assets[ path + '.' + ext ]
38
+ content_type asset.content_type
39
+ params[ :body ] ? asset.body : asset
40
+ end
41
+
42
+ get '/*' do
43
+ if !request.websocket?
44
+ settings.assets[ 'application.html' ]
45
+ else
46
+ request.websocket do |client|
47
+ client.onopen { onopen client }
48
+ client.onmessage { |message| onmessage( client, JSON.parse( message ).keys_to_sym! ) }
49
+ client.onclose { onclose client }
50
+ end
51
+ end
52
+ end
53
+
54
+ def onopen( client )
55
+ clients << client
56
+ client_connected client
57
+ end
58
+
59
+ def onmessage( client, message )
60
+ if controller = Object.const_get( message[ :controller ].capitalize + 'Controller' )
61
+ controller = controller.new( client, message )
62
+ if controller.methods.include?( action = message[ :action ].to_sym )
63
+ controller.send action
64
+ else puts "Action #{ action } not exists in #{ controller }" end
65
+ else puts "Controller #{ controller } not exists" end
66
+ on_message client, message
67
+ end
68
+
69
+ def onclose( client )
70
+ clients.delete client
71
+ client_disconnected client
72
+ end
73
+
74
+ def client_connected( client )
75
+ end
76
+
77
+ def on_message( client, message )
78
+ end
79
+
80
+ def client_disconnected( client )
81
+ end
82
+
83
+ def clients
84
+ self.class.clients
85
+ end
86
+
87
+ def self.clients
88
+ @@clients ||= []
89
+ end
90
+
91
+ def self.initialize!
92
+ Dir[ File.join( root, 'lib/*/**/*.rb' ) ].each { |file| require( file ) }
93
+ Dir[ File.join( root, 'app/*/**/*.rb' ) ].each { |file| require( file ) }
94
+ Dir[ File.join( root, 'vendor/*/**/*.rb' ) ].each { |file| require( file ) }
95
+ require File.join( root, 'config/application' )
96
+ self
97
+ end
98
+
99
+ def self.tasks
100
+ initialize!
101
+ require 'sinatra/activerecord/rake'
102
+ require 'rake/sprocketstask'
103
+ Rake::SprocketsTask.new do |task|
104
+ task.environment = settings.assets
105
+ task.output = File.join( public_folder, 'assets' )
106
+ task.assets = %w( application.html application.js application.css )
107
+ end
108
+ end
109
+
110
+ end
111
+
112
+ end
@@ -0,0 +1,96 @@
1
+ module EventMachine
2
+ module WebSocket
3
+ class Connection
4
+
5
+
6
+ def filters( model_name )
7
+ @filters ||= {}
8
+ @filters[ model_name ] ||= []
9
+ end
10
+
11
+ def filters_add( model_name, new_filter )
12
+ unless( new_filter.keys.include?( :id ) and new_filter.keys.length == 1 )
13
+ exist = false
14
+ filters( model_name ).each { |filter| exist = true if filter.sort.to_s == new_filter.sort.to_s }
15
+ filters( model_name ) << new_filter unless exist
16
+ end
17
+ end
18
+
19
+ def filter?( model )
20
+ filters( model.class.name.to_sym ).each do |filter|
21
+ result = true
22
+ filter.each { |key, value| result = false if model[ key ] != value }
23
+ return result if result
24
+ end
25
+ false
26
+ end
27
+
28
+ def []( name )
29
+ @storage ||= {}
30
+ @storage[ name ] or nil
31
+ end
32
+
33
+ def []=( name, value = false )
34
+ @storage ||= {}
35
+ @storage[ name ] = value
36
+ end
37
+
38
+ def watches
39
+ @watches ||= {}
40
+ end
41
+
42
+ def watch( model )
43
+ watches[ model.class.name + model.id.to_s ] ||= 0
44
+ end
45
+
46
+ def watch?( model )
47
+ if watches[ model.class.name + model.id.to_s ] then true else false end
48
+ end
49
+
50
+ def watch_time( model )
51
+ watches[ model.class.name + model.id.to_s ] or 0
52
+ end
53
+
54
+ def watch_time_up( model )
55
+ watches[ model.class.name + model.id.to_s ] = model.updated_at.to_f
56
+ end
57
+
58
+ def send_json( hash )
59
+ send hash.to_json
60
+ end
61
+
62
+ def sync( model )
63
+ if model.sync_access( self ) and ( watch_time( model ) < model.updated_at.to_f or model.destroyed? )
64
+ watch_time_up model
65
+ model.get_sync_models( self ).each { |relation| sync relation } unless model.destroyed?
66
+ send_json( { action: 'sync', params: model.get_sync_params( self ) } )
67
+ end
68
+ end
69
+
70
+ def notice( name, *args )
71
+ message = { action: :notice, notice: name }
72
+ if args[0].is_a?( ActiveRecord::Base )
73
+ model, params = args
74
+ message[ :model ] = "#{ model.class.name }.#{ model.id }"
75
+ else
76
+ params = args[0]
77
+ end
78
+ message[ :params ] = params
79
+ send_json message
80
+ end
81
+
82
+ def info( params )
83
+ notice :info, params
84
+ end
85
+
86
+ def warning( params )
87
+ notice :warning, params
88
+ end
89
+
90
+ def error( params )
91
+ notice :error, params
92
+ end
93
+
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,68 @@
1
+ module Nali
2
+
3
+ module Controller
4
+
5
+ attr_reader :client, :params, :message
6
+
7
+ def initialize( client, message )
8
+ @client = client
9
+ @message = message
10
+ @params = message[ :params ]
11
+ end
12
+
13
+ def clients
14
+ Nali::Application.clients
15
+ end
16
+
17
+ def save
18
+ if params[ :id ]
19
+ if model = model_class.find_by_id( params[ :id ] )
20
+ save_success( model ) if model.update_attributes( params )
21
+ end
22
+ else
23
+ if ( model = model_class.new( params ) ).valid?
24
+ save_success( model ) if model.save
25
+ end
26
+ end
27
+ end
28
+
29
+ def save_success( model )
30
+ on_save( model ) if self.methods.include?( :on_save )
31
+ trigger_success model.get_sync_params( client )
32
+ model.sync client
33
+ end
34
+
35
+ def select
36
+ model_class.where( params ).each { |model| client.sync model }
37
+ client.filters_add model_name, params
38
+ end
39
+
40
+ def destroy
41
+ if model = model_class.find_by_id( params[ :id ] )
42
+ on_destroy( model ) if self.methods.include?( :on_destroy )
43
+ model.destroy()
44
+ model.sync
45
+ end
46
+ end
47
+
48
+ def trigger_success( params = nil )
49
+ client.send_json( { action: 'success', params: params, journal_id: message[ :journal_id ] } )
50
+ end
51
+
52
+ def trigger_failure( params = nil )
53
+ client.send_json( { action: 'failure', params: params, journal_id: message[ :journal_id ] } )
54
+ end
55
+
56
+ private
57
+
58
+ def model_class
59
+ Object.const_get model_name
60
+ end
61
+
62
+ def model_name
63
+ self.class.name.gsub( 'sController', '' ).to_sym
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,11 @@
1
+ class Object
2
+
3
+ def keys_to_sym!
4
+ self.keys.each do |key|
5
+ self[ key ].keys_to_sym! if self[ key ].is_a?( Hash ) || self[ key ].is_a?( Array )
6
+ self[ ( key.to_sym rescue key ) ] = self.delete( key )
7
+ end
8
+ self
9
+ end
10
+
11
+ end
@@ -0,0 +1,18 @@
1
+ module Sprockets
2
+ module Helpers
3
+
4
+ def templates_tags
5
+ result = ''
6
+ Dir[ File.join( './app/templates/*/*' ) ].each do |path|
7
+ arr = path.split( '/' ).reverse
8
+ id = arr[1] + '_' + arr[0].split( '.' )[0]
9
+ asset = environment[ path ]
10
+ template = asset.body.force_encoding 'UTF-8'
11
+ result += %Q(\n<script type=\"text/template\" id=\"#{ id }\">\n#{ template }\n</script>)
12
+ depend_on asset.pathname
13
+ end
14
+ result
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,48 @@
1
+ module Nali
2
+
3
+ module Model
4
+
5
+ def sync_access( client )
6
+ true
7
+ end
8
+
9
+ def sync_models( client )
10
+ []
11
+ end
12
+
13
+ def sync_params( client )
14
+ {}
15
+ end
16
+
17
+ def get_sync_models( client )
18
+ ( [] << sync_models( client ) ).flatten.compact
19
+ end
20
+
21
+ def get_sync_params( client )
22
+ attributes = sync_params( client )
23
+ attributes[ :id ] = self.id
24
+ {
25
+ attributes: attributes,
26
+ created: self.created_at.to_f,
27
+ updated: self.updated_at.to_f,
28
+ sysname: self.class.name,
29
+ destroyed: self.destroyed?
30
+ }
31
+ end
32
+
33
+ def clients
34
+ Nali::Application.clients
35
+ end
36
+
37
+ def sync( *watches )
38
+ watches.flatten.each { |client| client.watch self }
39
+ clients.each { |client| client.sync self if client.watch?( self ) or client.filter?( self ) }
40
+ end
41
+
42
+ def notice( name, params )
43
+ clients.each { |client| client.notice self, name, params if client.watch?( self ) }
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,3 @@
1
+ module Nali
2
+ VERSION = "0.0.2"
3
+ end
metadata ADDED
@@ -0,0 +1,279 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nali
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - 4urbanoff
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-10-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thin
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sinatra
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: sinatra-websocket
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: sinatra-activerecord
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: sinatra-reloader
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: sprockets
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: sprockets-sass
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: sprockets-helpers
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :runtime
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: coffee-script
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :runtime
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: sass
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :runtime
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ - !ruby/object:Gem::Dependency
175
+ name: sqlite3
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :runtime
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ - !ruby/object:Gem::Dependency
191
+ name: bundler
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ~>
196
+ - !ruby/object:Gem::Version
197
+ version: '1.3'
198
+ type: :development
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ~>
204
+ - !ruby/object:Gem::Version
205
+ version: '1.3'
206
+ - !ruby/object:Gem::Dependency
207
+ name: rake
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ description: Realtime app
223
+ email:
224
+ - 4urbanoff@gmail.com
225
+ executables: []
226
+ extensions: []
227
+ extra_rdoc_files: []
228
+ files:
229
+ - lib/nali.rb
230
+ - lib/assets/javascripts/nali/view.js.coffee
231
+ - lib/assets/javascripts/nali/cookie.js.coffee
232
+ - lib/assets/javascripts/nali/nali.js.coffee
233
+ - lib/assets/javascripts/nali/notice.js.coffee
234
+ - lib/assets/javascripts/nali/controller.js.coffee
235
+ - lib/assets/javascripts/nali/jbone.min.js
236
+ - lib/assets/javascripts/nali/extensions.js.coffee
237
+ - lib/assets/javascripts/nali/model.js.coffee
238
+ - lib/assets/javascripts/nali/router.js.coffee
239
+ - lib/assets/javascripts/nali/collection.js.coffee
240
+ - lib/assets/javascripts/nali/index.js.coffee
241
+ - lib/assets/javascripts/nali/application.js.coffee
242
+ - lib/assets/javascripts/nali/connection.js.coffee
243
+ - lib/nali/extensions.rb
244
+ - lib/nali/model.rb
245
+ - lib/nali/controller.rb
246
+ - lib/nali/connection.rb
247
+ - lib/nali/version.rb
248
+ - lib/nali/helpers.rb
249
+ - lib/nali/application.rb
250
+ - LICENSE.txt
251
+ - Rakefile
252
+ - Gemfile
253
+ - README.md
254
+ homepage: https://github.com/4urbanoff/nali
255
+ licenses:
256
+ - MIT
257
+ post_install_message:
258
+ rdoc_options: []
259
+ require_paths:
260
+ - lib
261
+ required_ruby_version: !ruby/object:Gem::Requirement
262
+ none: false
263
+ requirements:
264
+ - - ! '>='
265
+ - !ruby/object:Gem::Version
266
+ version: '0'
267
+ required_rubygems_version: !ruby/object:Gem::Requirement
268
+ none: false
269
+ requirements:
270
+ - - ! '>='
271
+ - !ruby/object:Gem::Version
272
+ version: '0'
273
+ requirements: []
274
+ rubyforge_project:
275
+ rubygems_version: 1.8.25
276
+ signing_key:
277
+ specification_version: 3
278
+ summary: summary
279
+ test_files: []