nali 0.0.2

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.
@@ -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: []