leonidas 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +105 -0
- data/LICENSE +21 -0
- data/Manifest +63 -0
- data/README.md +213 -0
- data/Rakefile +42 -0
- data/assets/scripts/coffee/leonidas/client.coffee +15 -0
- data/assets/scripts/coffee/leonidas/commander.coffee +34 -0
- data/assets/scripts/coffee/leonidas/commands/command.coffee +9 -0
- data/assets/scripts/coffee/leonidas/commands/organizer.coffee +24 -0
- data/assets/scripts/coffee/leonidas/commands/processor.coffee +13 -0
- data/assets/scripts/coffee/leonidas/commands/stabilizer.coffee +13 -0
- data/assets/scripts/coffee/leonidas/commands/synchronizer.coffee +38 -0
- data/assets/scripts/js/lib/jquery.js +6 -0
- data/bin/leonidas.js +178 -0
- data/config/assets.rb +7 -0
- data/leonidas.gemspec +36 -0
- data/lib/leonidas.rb +14 -0
- data/lib/leonidas/app/app.rb +80 -0
- data/lib/leonidas/app/connection.rb +20 -0
- data/lib/leonidas/app/repository.rb +41 -0
- data/lib/leonidas/commands/aggregator.rb +31 -0
- data/lib/leonidas/commands/command.rb +24 -0
- data/lib/leonidas/commands/handler.rb +21 -0
- data/lib/leonidas/commands/processor.rb +30 -0
- data/lib/leonidas/dsl/configuration_expression.rb +17 -0
- data/lib/leonidas/memory_layer/memory_registry.rb +33 -0
- data/lib/leonidas/persistence_layer/persister.rb +54 -0
- data/lib/leonidas/persistence_layer/state_builder.rb +17 -0
- data/lib/leonidas/persistence_layer/state_loader.rb +22 -0
- data/lib/leonidas/routes/sync.rb +45 -0
- data/lib/leonidas/symbols.rb +17 -0
- data/spec/jasmine/jasmine.yml +44 -0
- data/spec/jasmine/runner.html +77 -0
- data/spec/jasmine/support/classes.coffee +16 -0
- data/spec/jasmine/support/helpers.coffee +22 -0
- data/spec/jasmine/support/mocks.coffee +19 -0
- data/spec/jasmine/support/objects.coffee +11 -0
- data/spec/jasmine/support/requirements.coffee +1 -0
- data/spec/jasmine/tests/client_spec.coffee +20 -0
- data/spec/jasmine/tests/commander_spec.coffee +69 -0
- data/spec/jasmine/tests/commands/command_spec.coffee +12 -0
- data/spec/jasmine/tests/commands/organizer_spec.coffee +70 -0
- data/spec/jasmine/tests/commands/processor_spec.coffee +22 -0
- data/spec/jasmine/tests/commands/stabilizer_spec.coffee +30 -0
- data/spec/jasmine/tests/commands/synchronizer_spec.coffee +72 -0
- data/spec/rspec/spec_helper.rb +4 -0
- data/spec/rspec/support/classes/app.rb +26 -0
- data/spec/rspec/support/classes/commands.rb +52 -0
- data/spec/rspec/support/classes/persistence.rb +56 -0
- data/spec/rspec/support/config.rb +3 -0
- data/spec/rspec/support/mocks.rb +15 -0
- data/spec/rspec/support/objects.rb +11 -0
- data/spec/rspec/unit/app/app_spec.rb +185 -0
- data/spec/rspec/unit/app/repository_spec.rb +114 -0
- data/spec/rspec/unit/commands/aggregator_spec.rb +103 -0
- data/spec/rspec/unit/commands/command.rb +17 -0
- data/spec/rspec/unit/commands/processor_spec.rb +30 -0
- data/spec/rspec/unit/dsl/configuration_expression_spec.rb +32 -0
- data/spec/rspec/unit/leonidas_spec.rb +26 -0
- data/spec/rspec/unit/memory_layer/memory_registry_spec.rb +85 -0
- data/spec/rspec/unit/persistence_layer/persister_spec.rb +84 -0
- data/spec/rspec/unit/persistence_layer/state_loader_spec.rb +29 -0
- metadata +166 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
v0.0.1 initial library
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/jpeace/keystone.git
|
3
|
+
revision: 54627ade405d8b3307e349f36bab6e87b75fae84
|
4
|
+
specs:
|
5
|
+
keystone (0.0.1)
|
6
|
+
closure-compiler
|
7
|
+
coffee-script
|
8
|
+
sass
|
9
|
+
sinatra
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: http://rubygems.org/
|
13
|
+
specs:
|
14
|
+
allison (2.0.3)
|
15
|
+
childprocess (0.3.9)
|
16
|
+
ffi (~> 1.0, >= 1.0.11)
|
17
|
+
closure-compiler (1.1.8)
|
18
|
+
coffee-script (2.2.0)
|
19
|
+
coffee-script-source
|
20
|
+
execjs
|
21
|
+
coffee-script-source (1.6.2)
|
22
|
+
columnize (0.3.6)
|
23
|
+
debugger (1.5.0)
|
24
|
+
columnize (>= 0.3.1)
|
25
|
+
debugger-linecache (~> 1.2.0)
|
26
|
+
debugger-ruby_core_source (~> 1.2.0)
|
27
|
+
debugger-linecache (1.2.0)
|
28
|
+
debugger-ruby_core_source (1.2.0)
|
29
|
+
diff-lcs (1.2.4)
|
30
|
+
echoe (4.6.3)
|
31
|
+
allison (>= 2.0.3)
|
32
|
+
gemcutter (>= 0.7.0)
|
33
|
+
rake (>= 0.9.2)
|
34
|
+
rdoc (>= 3.6.1)
|
35
|
+
rubyforge (>= 2.0.4)
|
36
|
+
execjs (1.4.0)
|
37
|
+
multi_json (~> 1.0)
|
38
|
+
ffi (1.8.1)
|
39
|
+
gemcutter (0.7.1)
|
40
|
+
hike (1.2.2)
|
41
|
+
jasmine (1.3.2)
|
42
|
+
jasmine-core (~> 1.3.1)
|
43
|
+
rack (~> 1.0)
|
44
|
+
rspec (>= 1.3.1)
|
45
|
+
selenium-webdriver (>= 0.1.3)
|
46
|
+
jasmine-core (1.3.1)
|
47
|
+
jasmine-headless-webkit (0.8.4)
|
48
|
+
coffee-script
|
49
|
+
jasmine-core (~> 1.1)
|
50
|
+
multi_json
|
51
|
+
rainbow
|
52
|
+
sprockets (~> 2)
|
53
|
+
json (1.7.7)
|
54
|
+
json_pure (1.7.7)
|
55
|
+
multi_json (1.7.2)
|
56
|
+
rack (1.5.2)
|
57
|
+
rack-protection (1.5.0)
|
58
|
+
rack
|
59
|
+
rainbow (1.1.4)
|
60
|
+
rake (10.0.4)
|
61
|
+
rdoc (4.0.1)
|
62
|
+
json (~> 1.4)
|
63
|
+
rspec (2.13.0)
|
64
|
+
rspec-core (~> 2.13.0)
|
65
|
+
rspec-expectations (~> 2.13.0)
|
66
|
+
rspec-mocks (~> 2.13.0)
|
67
|
+
rspec-core (2.13.1)
|
68
|
+
rspec-expectations (2.13.0)
|
69
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
70
|
+
rspec-mocks (2.13.1)
|
71
|
+
rubyforge (2.0.4)
|
72
|
+
json_pure (>= 1.1.7)
|
73
|
+
rubyzip (0.9.9)
|
74
|
+
sass (3.2.8)
|
75
|
+
selenium-webdriver (2.32.1)
|
76
|
+
childprocess (>= 0.2.5)
|
77
|
+
multi_json (~> 1.0)
|
78
|
+
rubyzip
|
79
|
+
websocket (~> 1.0.4)
|
80
|
+
sinatra (1.4.2)
|
81
|
+
rack (~> 1.5, >= 1.5.2)
|
82
|
+
rack-protection (~> 1.4)
|
83
|
+
tilt (~> 1.3, >= 1.3.4)
|
84
|
+
sprockets (2.9.3)
|
85
|
+
hike (~> 1.2)
|
86
|
+
multi_json (~> 1.0)
|
87
|
+
rack (~> 1.0)
|
88
|
+
tilt (~> 1.1, != 1.3.0)
|
89
|
+
tilt (1.4.0)
|
90
|
+
websocket (1.0.7)
|
91
|
+
|
92
|
+
PLATFORMS
|
93
|
+
ruby
|
94
|
+
|
95
|
+
DEPENDENCIES
|
96
|
+
debugger
|
97
|
+
echoe
|
98
|
+
jasmine
|
99
|
+
jasmine-headless-webkit
|
100
|
+
json
|
101
|
+
keystone!
|
102
|
+
rack
|
103
|
+
rake
|
104
|
+
rspec
|
105
|
+
sinatra
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Tim Shelburne
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
Gemfile
|
3
|
+
Gemfile.lock
|
4
|
+
LICENSE
|
5
|
+
Manifest
|
6
|
+
README.md
|
7
|
+
Rakefile
|
8
|
+
assets/scripts/coffee/leonidas/client.coffee
|
9
|
+
assets/scripts/coffee/leonidas/commander.coffee
|
10
|
+
assets/scripts/coffee/leonidas/commands/command.coffee
|
11
|
+
assets/scripts/coffee/leonidas/commands/organizer.coffee
|
12
|
+
assets/scripts/coffee/leonidas/commands/processor.coffee
|
13
|
+
assets/scripts/coffee/leonidas/commands/stabilizer.coffee
|
14
|
+
assets/scripts/coffee/leonidas/commands/synchronizer.coffee
|
15
|
+
assets/scripts/js/lib/jquery.js
|
16
|
+
bin/leonidas.js
|
17
|
+
config/assets.rb
|
18
|
+
lib/leonidas.rb
|
19
|
+
lib/leonidas/app/app.rb
|
20
|
+
lib/leonidas/app/connection.rb
|
21
|
+
lib/leonidas/app/repository.rb
|
22
|
+
lib/leonidas/commands/aggregator.rb
|
23
|
+
lib/leonidas/commands/command.rb
|
24
|
+
lib/leonidas/commands/handler.rb
|
25
|
+
lib/leonidas/commands/processor.rb
|
26
|
+
lib/leonidas/dsl/configuration_expression.rb
|
27
|
+
lib/leonidas/memory_layer/memory_registry.rb
|
28
|
+
lib/leonidas/persistence_layer/persister.rb
|
29
|
+
lib/leonidas/persistence_layer/state_builder.rb
|
30
|
+
lib/leonidas/persistence_layer/state_loader.rb
|
31
|
+
lib/leonidas/routes/sync.rb
|
32
|
+
lib/leonidas/symbols.rb
|
33
|
+
spec/jasmine/jasmine.yml
|
34
|
+
spec/jasmine/runner.html
|
35
|
+
spec/jasmine/support/classes.coffee
|
36
|
+
spec/jasmine/support/helpers.coffee
|
37
|
+
spec/jasmine/support/mocks.coffee
|
38
|
+
spec/jasmine/support/objects.coffee
|
39
|
+
spec/jasmine/support/requirements.coffee
|
40
|
+
spec/jasmine/tests/client_spec.coffee
|
41
|
+
spec/jasmine/tests/commander_spec.coffee
|
42
|
+
spec/jasmine/tests/commands/command_spec.coffee
|
43
|
+
spec/jasmine/tests/commands/organizer_spec.coffee
|
44
|
+
spec/jasmine/tests/commands/processor_spec.coffee
|
45
|
+
spec/jasmine/tests/commands/stabilizer_spec.coffee
|
46
|
+
spec/jasmine/tests/commands/synchronizer_spec.coffee
|
47
|
+
spec/rspec/spec_helper.rb
|
48
|
+
spec/rspec/support/classes/app.rb
|
49
|
+
spec/rspec/support/classes/commands.rb
|
50
|
+
spec/rspec/support/classes/persistence.rb
|
51
|
+
spec/rspec/support/config.rb
|
52
|
+
spec/rspec/support/mocks.rb
|
53
|
+
spec/rspec/support/objects.rb
|
54
|
+
spec/rspec/unit/app/app_spec.rb
|
55
|
+
spec/rspec/unit/app/repository_spec.rb
|
56
|
+
spec/rspec/unit/commands/aggregator_spec.rb
|
57
|
+
spec/rspec/unit/commands/command.rb
|
58
|
+
spec/rspec/unit/commands/processor_spec.rb
|
59
|
+
spec/rspec/unit/dsl/configuration_expression_spec.rb
|
60
|
+
spec/rspec/unit/leonidas_spec.rb
|
61
|
+
spec/rspec/unit/memory_layer/memory_registry_spec.rb
|
62
|
+
spec/rspec/unit/persistence_layer/persister_spec.rb
|
63
|
+
spec/rspec/unit/persistence_layer/state_loader_spec.rb
|
data/README.md
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
# Leonidas
|
2
|
+
|
3
|
+
leonidas.js handles generalized web application concurrency through basic command operations. It handles synchronizing application state by sending serialized lists of local commands and retrieving commands processed on external commands to and from a server with AJAX.
|
4
|
+
|
5
|
+
Leonidas.rb is an integration built to support Leonidas commands on the server-side, in both memory and persistent states. There are also two default Sinatra endpoints provided at Leonidas::Routes::SyncApp for an immediate integration with leonidas.js.
|
6
|
+
|
7
|
+
## Terminology
|
8
|
+
|
9
|
+
### General
|
10
|
+
|
11
|
+
* Command - Any granular action taken within an application
|
12
|
+
* Command Handler - An class representing an action taken on the application state in response to a command
|
13
|
+
* Stable Command - A command that happened before or at the minimum timestamp of all client connections to the app
|
14
|
+
* Locked State - The state of an application when only stable commands have been run
|
15
|
+
* Active State - The state of an application when all available commands have been run
|
16
|
+
|
17
|
+
### Javascript
|
18
|
+
|
19
|
+
* Client - A wrapper around the client-side application state, representing a single client connection to the server
|
20
|
+
* Commander - The command abstraction, used to start and stop syncing, and issue commands
|
21
|
+
|
22
|
+
### Ruby
|
23
|
+
|
24
|
+
* App - A server side application which keeps track of state and client connections
|
25
|
+
* Connection - The server side implementation of a client containing a list of commands
|
26
|
+
* Repository - The mechanism for retrieving an active application
|
27
|
+
* Persister - A class responsible for providing the methods necessary to persist an app in a particular system
|
28
|
+
* State Builder - A class responsible for rebuilding the state of a persisted application to be loaded into memory
|
29
|
+
|
30
|
+
## Configuration
|
31
|
+
|
32
|
+
### Javascript
|
33
|
+
|
34
|
+
No configuration is needed on the client side.
|
35
|
+
|
36
|
+
### Ruby
|
37
|
+
|
38
|
+
Persistence of commands in your system will be handled in the server side command handlers, but if your application details need to be persisted, there are only two functions necessary to configure Leonidas:
|
39
|
+
|
40
|
+
* persister\_class\_is(persister\_class) - The class responsible for handling persisting the application will be passed into this function
|
41
|
+
|
42
|
+
* add\_app\_state\_builder(builder\_class) - For every application you need to support, you will likely need a custom state builder to generate the appropriate state for that application
|
43
|
+
|
44
|
+
And example config would resemble the following:
|
45
|
+
|
46
|
+
persister_class_is SaveMyTransgressions
|
47
|
+
|
48
|
+
add_app_state_builder Builders::PeasantStateBuilder
|
49
|
+
add_app_state_builder Buidlers::AristocraticStateBuilder
|
50
|
+
|
51
|
+
## Usage
|
52
|
+
|
53
|
+
### Javascript
|
54
|
+
|
55
|
+
First, create at least one handler for commands in your system (I'm going to use Coffeescript, because it's so nice):
|
56
|
+
|
57
|
+
class PeasantHitHandler
|
58
|
+
|
59
|
+
constructor: (@app)-> # this is temporary - I would much rather be passing in @peasants, but object duplication in Javascript is tricky
|
60
|
+
|
61
|
+
handles: (command)->
|
62
|
+
command.name == "peasant-hit"
|
63
|
+
|
64
|
+
run: (command)->
|
65
|
+
peasantId = command.data.peasantId
|
66
|
+
... find peasant in @app.state by peasantId
|
67
|
+
peasant.status = "humbled"
|
68
|
+
|
69
|
+
Then, you can create a Commander (I would suggest using the default configuration, unless you need custom functionality in the nitty gritty):
|
70
|
+
|
71
|
+
var supremeRuler = Commander.default("app name", [ new PeasantHitHandler() ], "http://mydomain.com/my/sync/url")
|
72
|
+
|
73
|
+
Now you can start and stop syncing and issue commands to your hearts content:
|
74
|
+
|
75
|
+
supremeRuler.startSync() # not the funniest line... oh well
|
76
|
+
supremeRuler.issueCommand("peasant-hit", { peasantId: 10 })
|
77
|
+
|
78
|
+
This will automatically be handled and synced with your server, most importantly so that you will know if any ruthless rulers from other clients have been hitting your peasants.
|
79
|
+
|
80
|
+
### Ruby
|
81
|
+
|
82
|
+
As always, the server side is a bit more complicated.
|
83
|
+
|
84
|
+
First, you should create at least one command handler. Note that the handler will have the logic necessary to persist your changes - the mechanism for running commands is agnostic, so all persistence options are supported:
|
85
|
+
|
86
|
+
class PeasantHitHandler
|
87
|
+
include Leonidas::Commands::Handler # this just ensures that all necessary functions are available
|
88
|
+
|
89
|
+
def initialize(app) # similar problem - have to make sure object references work properly
|
90
|
+
@app = app
|
91
|
+
end
|
92
|
+
|
93
|
+
def handles?(command)
|
94
|
+
command.name == "peasant-hit"
|
95
|
+
end
|
96
|
+
|
97
|
+
def run(command)
|
98
|
+
peasant_id = command.data.peasantId # probably camel-cased - it came from js, after all
|
99
|
+
... # find peasant in @app.current_state.peasants by peasant_id
|
100
|
+
peasant.status = :humbled
|
101
|
+
end
|
102
|
+
|
103
|
+
def persist(command)
|
104
|
+
... # persistence logic - up to you, homie
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
Then, you can create an App:
|
109
|
+
|
110
|
+
class PeasantSubjugationApp
|
111
|
+
include Leonidas::App::App # this is the neat part that gives you a Leonidas App
|
112
|
+
|
113
|
+
def initialize
|
114
|
+
@name = "Kingdom-Zamunda" # this name must be unique amongst all your apps
|
115
|
+
@persist_state = true # this means that commands with be persisted when they are run
|
116
|
+
@locked_state = { peasants: [ ... ] } # this is the stable state of your application
|
117
|
+
@active_state = { peasants: [ ... ] } # this is the active state (memory only, never persisted) of your application
|
118
|
+
@connections = [ ] # an empty list of connections when an app is first built
|
119
|
+
@processor = Leonidas::Commands::Processor.new([ PeasantHitHandler.new(self) ]) # a processor initialized with the necessary command handlers
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
This is enough to have a functioning Leonidas app - of course, it's likely you will need customization to handle the semantic details of your state.
|
125
|
+
|
126
|
+
Now you want to run your app and rule your kingdom (from an endpoint in Sinatra):
|
127
|
+
|
128
|
+
include Leonidas::App::AppRepository # I recommend using the mixin, it makes the function available
|
129
|
+
|
130
|
+
get "/rule-zamunda" do
|
131
|
+
app = PeasantSubjugationApp.new
|
132
|
+
app_repository.watch app # now the app is being stored and referenced from memory
|
133
|
+
...
|
134
|
+
end
|
135
|
+
|
136
|
+
Eventually you need to load your app:
|
137
|
+
|
138
|
+
...
|
139
|
+
get "/i-want-to-rule-zamunda-too" do
|
140
|
+
app = app_repository.find "Kingdom-Zamunda"
|
141
|
+
...
|
142
|
+
haml :see_your_kingdom
|
143
|
+
end
|
144
|
+
|
145
|
+
Great! We now have an app running in memory, updating state, and if you did well, communicating to the client(s) at regular intervals.
|
146
|
+
|
147
|
+
But what if you (a) need to restart the machine and lose all of your state from memory, or (b) want to revive an old closed application? This is where a persistent application comes into play. A persistent application means simply that you have stored your application details, active connections, and commands in some sort of database. In order to reopen an application that has been closed, or restore an application to memory from disk, we need to be able to load the app from the database via a generalized solution.
|
148
|
+
|
149
|
+
Enter the persister:
|
150
|
+
|
151
|
+
class SaveMyTransgressions
|
152
|
+
include Leonidas::PersistenceLayer::AppPersister # this guarantees that the static Persister can use your class
|
153
|
+
|
154
|
+
def load(app_name)
|
155
|
+
... # your read / build logic (note that you don't need to worry hear about app state)
|
156
|
+
end
|
157
|
+
|
158
|
+
def persist(app_name)
|
159
|
+
... # your write logic
|
160
|
+
end
|
161
|
+
|
162
|
+
def delete(app)
|
163
|
+
... # your remove logic
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
The gist of filling out this class is to allow communication between your database and code to read / write app details (name, persist_state, connections) and connection details (id, last_update, active / inactive commands).
|
168
|
+
|
169
|
+
Once you have created your app persister, your application skeleton can be loaded - this just leaves catching the state up with whatever was current. All you need to do in this case is make sure you build the previous locked state of the application. All commands that happened after that locked state will be run again in memory to return your application to a live state.
|
170
|
+
|
171
|
+
Create your application's state builder:
|
172
|
+
|
173
|
+
module Builders
|
174
|
+
|
175
|
+
class PeasantStateBuilder
|
176
|
+
include Leonidas::PersistenceLayer::StateBuilder # this lets the state factory use this builder
|
177
|
+
|
178
|
+
def handles?(app)
|
179
|
+
app.is_a? PeasantSubjugationApp
|
180
|
+
end
|
181
|
+
|
182
|
+
def build_stable_state(app)
|
183
|
+
... # return the peasants to the fields, so to speak
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
Lastly, if you want to use the Sinatra endpoints provided by Leonidas for automatically syncing between your clients and server, the Rack app is available:
|
191
|
+
|
192
|
+
map "/path/you/like" do
|
193
|
+
run Leonidas::Routes::SyncApp
|
194
|
+
end
|
195
|
+
|
196
|
+
This will mean the frontend syncUrl you pass in Commander.default would look something like "http://yourdomain.com/path/you/like/[your-app-name]"
|
197
|
+
|
198
|
+
Voilá, your app should be good to go.
|
199
|
+
|
200
|
+
## If (and when) it isn't
|
201
|
+
|
202
|
+
Please feel free to contribute, or submit issues to the tracker!
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
|
208
|
+
|
209
|
+
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
$: << File.expand_path("#{File.dirname(__FILE__)}/lib")
|
2
|
+
|
3
|
+
require 'leonidas'
|
4
|
+
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
require 'jasmine-headless-webkit'
|
7
|
+
require 'keystone'
|
8
|
+
require 'echoe'
|
9
|
+
|
10
|
+
Echoe.new("leonidas") do |p|
|
11
|
+
p.author = "Tim Shelburne"
|
12
|
+
p.email = "shelburt02@gmail.com"
|
13
|
+
p.url = "https://github.com/tshelburne/leonidas"
|
14
|
+
|
15
|
+
p.ignore_pattern = FileList[".gitignore"]
|
16
|
+
p.development_dependencies = [ "jasmine", "jasmine-headless-webkit" ]
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Default"
|
20
|
+
task default: :'test:rspec'
|
21
|
+
|
22
|
+
namespace :test do
|
23
|
+
|
24
|
+
desc "Run Rspec tests"
|
25
|
+
RSpec::Core::RakeTask.new(:rspec) do |t|
|
26
|
+
t.rspec_opts = "-dcfd --require rspec/spec_helper"
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Run Jasmine tests"
|
30
|
+
Jasmine::Headless::Task.new(jasmine: :assets) do |t|
|
31
|
+
t.colors = true
|
32
|
+
t.keep_on_error = true
|
33
|
+
t.jasmine_config = './spec/jasmine/jasmine.yml'
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Build assets"
|
39
|
+
Keystone::RakeTask.new :assets do |t|
|
40
|
+
t.config_file = "config/assets.rb"
|
41
|
+
t.output_path = 'bin'
|
42
|
+
end
|