circuit 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +34 -0
- data/LICENSE +20 -0
- data/README.md +161 -0
- data/Rakefile +27 -0
- data/config.ru +7 -0
- data/description.md +5 -0
- data/docs/COMPATIBILITY.md +14 -0
- data/docs/ROADMAP.md +29 -0
- data/lib/circuit.rb +125 -0
- data/lib/circuit/behavior.rb +99 -0
- data/lib/circuit/compatibility.rb +73 -0
- data/lib/circuit/middleware.rb +6 -0
- data/lib/circuit/middleware/rewriter.rb +43 -0
- data/lib/circuit/rack.rb +14 -0
- data/lib/circuit/rack/behavioral.rb +45 -0
- data/lib/circuit/rack/builder.rb +50 -0
- data/lib/circuit/rack/multi_site.rb +22 -0
- data/lib/circuit/rack/request.rb +81 -0
- data/lib/circuit/railtie.rb +24 -0
- data/lib/circuit/storage.rb +74 -0
- data/lib/circuit/storage/memory_model.rb +70 -0
- data/lib/circuit/storage/nodes.rb +56 -0
- data/lib/circuit/storage/nodes/memory_store.rb +63 -0
- data/lib/circuit/storage/nodes/model.rb +67 -0
- data/lib/circuit/storage/nodes/mongoid_store.rb +56 -0
- data/lib/circuit/storage/sites.rb +38 -0
- data/lib/circuit/storage/sites/memory_store.rb +53 -0
- data/lib/circuit/storage/sites/model.rb +29 -0
- data/lib/circuit/storage/sites/mongoid_store.rb +43 -0
- data/lib/circuit/validators.rb +74 -0
- data/lib/circuit/version.rb +3 -0
- data/spec/internal/app/behaviors/change_path.rb +7 -0
- data/spec/internal/app/controllers/application_controller.rb +5 -0
- data/spec/internal/app/helpers/application_helper.rb +2 -0
- data/spec/internal/config/initializers/circuit.rb +7 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/db/schema.rb +1 -0
- data/spec/lib/circuit/behavior_spec.rb +113 -0
- data/spec/lib/circuit/middleware/rewriter_spec.rb +79 -0
- data/spec/lib/circuit/rack/behavioral_spec.rb +60 -0
- data/spec/lib/circuit/rack/builder_spec.rb +125 -0
- data/spec/lib/circuit/rack/multi_site_spec.rb +34 -0
- data/spec/lib/circuit/rack/request_spec.rb +80 -0
- data/spec/lib/circuit/railtie_spec.rb +34 -0
- data/spec/lib/circuit/storage/nodes_spec.rb +62 -0
- data/spec/lib/circuit/storage/sites_spec.rb +60 -0
- data/spec/lib/circuit/storage_spec.rb +20 -0
- data/spec/lib/circuit/validators_spec.rb +69 -0
- data/spec/lib/circuit_spec.rb +139 -0
- data/spec/spec_helper.rb +79 -0
- data/spec/support/blueprints.rb +24 -0
- data/spec/support/matchers/be_current_time_matcher.rb +14 -0
- data/spec/support/matchers/extended_have_key.rb +31 -0
- data/spec/support/matchers/have_accessor_matcher.rb +13 -0
- data/spec/support/matchers/have_attribute_matcher.rb +22 -0
- data/spec/support/matchers/have_block_matcher.rb +14 -0
- data/spec/support/matchers/have_errors_on_matcher.rb +30 -0
- data/spec/support/matchers/have_module_matcher.rb +13 -0
- data/spec/support/matchers/have_reader_matcher.rb +18 -0
- data/spec/support/matchers/have_writer_matcher.rb +18 -0
- data/spec/support/matchers/set_instance_variable.rb +32 -0
- data/spec/support/spec_helpers/base_behaviors.rb +20 -0
- data/spec/support/spec_helpers/base_models.rb +64 -0
- data/spec/support/spec_helpers/logger_helpers.rb +58 -0
- data/spec/support/spec_helpers/multi_site_helper.rb +48 -0
- data/spec/support/spec_helpers/rack_helpers.rb +8 -0
- data/spec/support/spec_helpers/shared_examples/node_store.rb +87 -0
- data/spec/support/spec_helpers/shared_examples/site_store.rb +76 -0
- data/spec/support/spec_helpers/simple_machinable.rb +29 -0
- data/spec/support/spec_helpers/stores_cleaner.rb +46 -0
- data/vendor/active_support-3.2/core_ext/string/inflections.rb +53 -0
- data/vendor/active_support-3.2/inflector/methods.rb +65 -0
- data/vendor/rack-1.4/builder.rb +167 -0
- data/vendor/rack-1.4/urlmap.rb +96 -0
- metadata +238 -0
data/Gemfile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
group :development, :test do
|
4
|
+
gem "rake", "~> 0.9.2"
|
5
|
+
gem "combustion", "= 0.3.2"
|
6
|
+
gem "rspec-rails", "~> 2.9.0"
|
7
|
+
gem "shoulda-matchers", "~> 1.1.0"
|
8
|
+
gem "database_cleaner", "~> 0.7.2"
|
9
|
+
gem "mocha", "~> 0.11.4"
|
10
|
+
gem "rspec-rails-mocha", "~> 0.3.2"
|
11
|
+
gem "delorean", "~> 1.2.0"
|
12
|
+
gem "machinist", "~> 2.0.0.beta2"
|
13
|
+
gem "faker", "~> 1.0.1"
|
14
|
+
gem "simplecov", "~> 0.6.4", :require => false
|
15
|
+
end
|
16
|
+
|
17
|
+
group :development do
|
18
|
+
gem "yard", "~> 0.8"
|
19
|
+
gem "redcarpet", "~> 2.1"
|
20
|
+
end
|
21
|
+
|
22
|
+
group :mongo do
|
23
|
+
gem "mongoid", "~> 2.4"
|
24
|
+
gem "mongoid-tree", "~> 0.7"
|
25
|
+
gem "bson_ext", "~> 1.4"
|
26
|
+
gem "mongoid-rspec", "= 1.4.4"
|
27
|
+
gem "machinist_mongo",
|
28
|
+
:require => "machinist/mongoid",
|
29
|
+
:git => "git://github.com/nmerouze/machinist_mongo.git",
|
30
|
+
:branch => "machinist2"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Specify core dependencies in core.gemspec
|
34
|
+
gemspec
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 MaxMedia
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject
|
9
|
+
to the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included
|
12
|
+
in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
18
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
19
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
20
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
**Circuit is in heavy development and reorganization at the moment. We are planning to have this API and change
|
2
|
+
stabilized in the 0.4.0 release. 0.4.0 and future releases will include deprecation warning and a 0.4.0-stable
|
3
|
+
branch in GitHub.**
|
4
|
+
|
5
|
+
# Circuit
|
6
|
+
|
7
|
+
<<< description.md
|
8
|
+
|
9
|
+
**GitHub** http://github.com/maxmedia/circuit
|
10
|
+
|
11
|
+
**Issues** http://github.com/maxmedia/circuit/issues
|
12
|
+
|
13
|
+
**Travis-CI** http://travis-ci.org/maxmedia/circuit
|
14
|
+
[![Build Status](https://secure.travis-ci.org/maxmedia/circuit.png?branch=master)](http://travis-ci.org/maxmedia/circuit)
|
15
|
+
|
16
|
+
**Docs** http://rubydoc.info/gems/circuit
|
17
|
+
|
18
|
+
**RubyGems** http://rubygems.org/gems/circuit
|
19
|
+
|
20
|
+
## Contributing
|
21
|
+
|
22
|
+
Anyone is welcome to contribute to circuit. Just [fork us on GitHub](https://github.com/maxmedia/circuit/fork_select)
|
23
|
+
and send a pull request when you are ready.
|
24
|
+
|
25
|
+
Please ensure the following compatibility requirements are met.
|
26
|
+
|
27
|
+
<<< docs/COMPATIBILITY.md
|
28
|
+
|
29
|
+
## A common discussion ensues.
|
30
|
+
|
31
|
+
**Q: But why would someone need database powered Rack::Builder?**
|
32
|
+
|
33
|
+
Response: The rack ecosystem doesn't have a good way to handle dynamic http routing. Circuit meets the
|
34
|
+
needs of dynamic routing while preserving the functionality that Rack provides.
|
35
|
+
|
36
|
+
**Comment: That seems really... slow.**
|
37
|
+
|
38
|
+
Response: A valid point, but circuit isn't for every codebase. If you need dynamic routing (i.e.
|
39
|
+
using splat routing methods followed by a database lookup), you are going to see similar
|
40
|
+
performance to circuits backends. Along with that, circuit provides a number of useful features
|
41
|
+
that far outweigh performance costs.
|
42
|
+
|
43
|
+
**Comment: this isn't very _Railsy_**
|
44
|
+
|
45
|
+
Response: In practice, codebases that use circuit to solve dynamic routing are **more** railsy.
|
46
|
+
Let me explain:
|
47
|
+
|
48
|
+
If you are constructing an application in Rails that requires dynamic user specified slugs, you
|
49
|
+
probably have this line uncommented from your routes:
|
50
|
+
|
51
|
+
# yuck.
|
52
|
+
match '/*', to: 'site#proxy'
|
53
|
+
|
54
|
+
Say you are creating a CMS using this line. This means that that one action will handle all
|
55
|
+
requests that don't match the rest of your routes definition. Immediately this might seem like a good
|
56
|
+
idea, but it will inevitably lead to a very expensive Rails action that handles a large number of
|
57
|
+
requests on the site.
|
58
|
+
|
59
|
+
Circuit will allow you to remove this line and use middlewares to route requests to different
|
60
|
+
controllers (even rack applications), and control this logic via the backend of your choice.
|
61
|
+
Routes can be extended with their specified behaviors, allowing even more control over requests
|
62
|
+
than rails provides out of the box.
|
63
|
+
|
64
|
+
Using the Rerouting Middleware you can easily reroute downstream requests to standard-issue rails
|
65
|
+
controllers, enabling your dynamic requests to add middleware, modify the rack request object and
|
66
|
+
even change your downstream app (to another rack app).
|
67
|
+
|
68
|
+
## A mapping graph to route rack requests.
|
69
|
+
|
70
|
+
TODO
|
71
|
+
|
72
|
+
## Rackup-based behaviors.
|
73
|
+
|
74
|
+
Circuit uses behaviors to extend a requests functionality in the rack stack. Behaviors are written
|
75
|
+
and stored in circuit-rackup files (`.cru`). The difference between a normal rackup file and a
|
76
|
+
circuit-rackup file is that a circuit-rackup file does not have to have a `run` declaration; this
|
77
|
+
makes circuit-rackup files only *partially* rackup compliant. Below is an example of a behavior
|
78
|
+
that renders an ok response (this is a fully-compliant rackup file; however, we still use the
|
79
|
+
`.cru` extension for the behavior):
|
80
|
+
|
81
|
+
# ./app/behaviors/render_ok.cru
|
82
|
+
|
83
|
+
run proc {|env| [200, {'Content-Type' => 'text/plain'}, ['OK']] }
|
84
|
+
|
85
|
+
|
86
|
+
First, setup your `Site`:
|
87
|
+
|
88
|
+
$ > @site = Circuit::Site.new(host: "example.com", aliases: ["www.example.com"])
|
89
|
+
$ > @site.save
|
90
|
+
$ => true
|
91
|
+
|
92
|
+
Then, setup your `Node` and specify the behavior:
|
93
|
+
|
94
|
+
$ > @node = Circuit::Node.new(slug: "", behavior_klass: "RenderOk")
|
95
|
+
$ > @node.site = @site
|
96
|
+
$ > @node.save
|
97
|
+
$ => true
|
98
|
+
$ > @node.root? # the blank slug indicates the root
|
99
|
+
$ => true
|
100
|
+
$ > @node.behavior
|
101
|
+
$ => RenderOk
|
102
|
+
$ > @node.behavior.class
|
103
|
+
$ => Module
|
104
|
+
$ > @node.behavior.included_modules
|
105
|
+
$ => [Circuit::Behavior]
|
106
|
+
|
107
|
+
When your site is loaded, the render_ok.ru behavior will be executed.
|
108
|
+
|
109
|
+
Behaviors are loaded into memory during application initialization. Any modifications to behaviors
|
110
|
+
will require restarting your application.
|
111
|
+
|
112
|
+
## Circuit::Middleware::Rewriter
|
113
|
+
|
114
|
+
One useful middleware baked into circuit is the `Rewriter`. The idea of this middleware is
|
115
|
+
to use circuit routing to route to dynamic content you have associated in you routing tree.
|
116
|
+
|
117
|
+
# ./app/behaviors/page.ru
|
118
|
+
|
119
|
+
use Circuit::Middleware::Rewriter do |request|
|
120
|
+
content = request.route.last.content
|
121
|
+
["/#{content.class.to_s.underscore.pluralize}", "/#{content.id}"]
|
122
|
+
end
|
123
|
+
|
124
|
+
and the corresponding downstream rails file:
|
125
|
+
|
126
|
+
# ./config/routes.rb
|
127
|
+
|
128
|
+
Rails.application.routes.draw do
|
129
|
+
resources :contents
|
130
|
+
end
|
131
|
+
|
132
|
+
In the above example, we are assuming you have created a model that has a content object associated
|
133
|
+
to it. By doing this we have now created a small CMS.
|
134
|
+
|
135
|
+
## Multi-Backend support
|
136
|
+
|
137
|
+
Circuit provides support for different backends to power this map tree. Currently, the gem includes a
|
138
|
+
Mongoid backend and a memory backend. Each backend is how Circuit is constructed to interface with your
|
139
|
+
persisted routing tree. Backends are ActiveModel based.
|
140
|
+
|
141
|
+
Currently, Backends are ActiveModel backed and within them they define the model that the router interacts
|
142
|
+
with. We are discussing the idea of separating the backends from the model (to drop the ActiveModel dependency).
|
143
|
+
|
144
|
+
**This is where circuit needs your help!** We would love to see backends for many common ODM's. Our
|
145
|
+
hit-list includes:
|
146
|
+
|
147
|
+
* <del>Mongoid</del>
|
148
|
+
* <del>Memory</del>
|
149
|
+
* Yaml
|
150
|
+
* Redis
|
151
|
+
* ActiveRecord
|
152
|
+
* RiakClient/Ripple
|
153
|
+
|
154
|
+
We will entertain pull requests from other commonly used libraries.
|
155
|
+
|
156
|
+
<<< docs/ROADMAP.md
|
157
|
+
|
158
|
+
-----------------------------------------------
|
159
|
+
```
|
160
|
+
<<< LICENSE
|
161
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "pathname"
|
3
|
+
|
4
|
+
$rake_root = Pathname(__FILE__).expand_path.dirname
|
5
|
+
|
6
|
+
Dir.glob($rake_root.join("**/*.rake").to_s).each do |fn|
|
7
|
+
load fn
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => [:spec]
|
11
|
+
|
12
|
+
namespace :clobber do
|
13
|
+
desc "Clobber Gem Package (pkg/)"
|
14
|
+
task :pkg do
|
15
|
+
$rake_root.join("pkg").rmtree rescue nil
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Clobber Coverage (coverage/)"
|
19
|
+
task :coverage do
|
20
|
+
$rake_root.join("coverage").rmtree rescue nil
|
21
|
+
end
|
22
|
+
|
23
|
+
task :doc => ["doc:clobber"]
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Clobber All"
|
27
|
+
task :clobber => ["doc:clobber", "clobber:pkg", "clobber:coverage"]
|
data/config.ru
ADDED
data/description.md
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
Circuit is a rack application middleware that enables dynamic request mapping. Modeled after
|
2
|
+
[Rack::Builder](https://github.com/rack/rack/blob/master/lib/rack/builder.rb), Circuit provides
|
3
|
+
for a tree of url-mappings that is walked at request time. If you are interested in dynamically
|
4
|
+
loading middleware and functionality into requests, circuit is a viable solution to do that in a
|
5
|
+
maintainable way.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
## Compatibility
|
2
|
+
|
3
|
+
Circuit is compatible with the following versions of Ruby, Rack, and Rails components:
|
4
|
+
|
5
|
+
**Ruby** 1.8.7 and 1.9
|
6
|
+
*Ruby 1.8.7 support will be removed when Rails 4 support is added*
|
7
|
+
|
8
|
+
**Rack** 1.3 and 1.4
|
9
|
+
|
10
|
+
**Rails** 3.1 and 3.2
|
11
|
+
*ActiveSupport and ActiveModel are the only requirements from Rails*
|
12
|
+
|
13
|
+
**Mongoid** 2.4+
|
14
|
+
*MongoDB/Mongoid is not required*
|
data/docs/ROADMAP.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
## Roadmap
|
2
|
+
|
3
|
+
### 0.2.0
|
4
|
+
|
5
|
+
* <del>better readme</del>
|
6
|
+
* <del>Separate site and routing tree</del>
|
7
|
+
* <del>database site aliases</del>
|
8
|
+
* <del>multi-backend support</del>
|
9
|
+
* <del>travis-ci</del>
|
10
|
+
* <del>Move to github issues</del>
|
11
|
+
* <del>Remove rails dependencies (specifically ActionPack)</del>
|
12
|
+
* <del>Behaviors are specified in rackup files, instead of classes</del>
|
13
|
+
* <del>Behaviors support partial Rack::Builder: `run` and `use` methods<del>
|
14
|
+
|
15
|
+
### 0.2.1
|
16
|
+
* Behaviors support full Rack::Builder: `run`, `use`, and `map` methods.
|
17
|
+
|
18
|
+
### 0.3.0
|
19
|
+
|
20
|
+
* tree inheritable middlewares.
|
21
|
+
* full documentation.
|
22
|
+
|
23
|
+
### 0.4.0
|
24
|
+
|
25
|
+
* API stability
|
26
|
+
|
27
|
+
### In the future
|
28
|
+
|
29
|
+
* Goliath support
|
data/lib/circuit.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
if Object.const_defined?(:Rails)
|
2
|
+
require "circuit/railtie"
|
3
|
+
end
|
4
|
+
require 'logger'
|
5
|
+
require 'circuit/version'
|
6
|
+
require 'circuit/compatibility'
|
7
|
+
require 'active_support/configurable'
|
8
|
+
require 'dionysus/configuration_callbacks'
|
9
|
+
|
10
|
+
module Circuit
|
11
|
+
autoload :Middleware, 'circuit/middleware'
|
12
|
+
autoload :Rack, 'circuit/rack'
|
13
|
+
autoload :Behavior, 'circuit/behavior'
|
14
|
+
autoload :Storage, 'circuit/storage'
|
15
|
+
|
16
|
+
# Top-level error class for Circuit errorsr
|
17
|
+
class CircuitError < StandardError; end
|
18
|
+
|
19
|
+
# @!attribute [r] config
|
20
|
+
# Maintains configuration values for `logger`, `cru_path`, `site_store`,
|
21
|
+
# and `node_store`
|
22
|
+
# @return [ActiveSupport::Configurable::Configuration] configuration
|
23
|
+
# @see http://rubydoc.info/gems/activesupport/ActiveSupport/Configurable/ClassMethods#config-instance_method
|
24
|
+
|
25
|
+
# @!method configure()
|
26
|
+
# Configure Circuit
|
27
|
+
# @yield [ActiveSupport::Configurable::Configuration] configuration object
|
28
|
+
# @see http://rubydoc.info/gems/activesupport/ActiveSupport/Configurable/ClassMethods#configure-instance_method
|
29
|
+
include ActiveSupport::Configurable
|
30
|
+
include Dionysus::ConfigurationCallbacks
|
31
|
+
config_accessor :logger, :cru_path, :site_store, :node_store,
|
32
|
+
:instance_reader => false,
|
33
|
+
:instance_writer => false
|
34
|
+
|
35
|
+
# @!method logger=(logger)
|
36
|
+
# @!scope class
|
37
|
+
# @param [Logger] logger for Circuit
|
38
|
+
# @return [Logger] logger for Circuit
|
39
|
+
|
40
|
+
# @!method logger
|
41
|
+
# @!scope class
|
42
|
+
# @return [Logger] logger for Circuit
|
43
|
+
|
44
|
+
# @!method cru_path=(pathname)
|
45
|
+
# @!scope class
|
46
|
+
# @param [Pathname,String] pathname directory for behaviors, .cru, and .ru files
|
47
|
+
# @return [Pathname] pathname directory for behaviors, .cru, and .ru files
|
48
|
+
|
49
|
+
# @!method cru_path
|
50
|
+
# @!scope class
|
51
|
+
# @return [Pathname] pathname directory for behaviors, .cru, and .ru files
|
52
|
+
|
53
|
+
# @!method site_store
|
54
|
+
# @!scope class
|
55
|
+
# @return [Storage::Sites::BaseStore] the Site storage instance
|
56
|
+
|
57
|
+
# @!method node_store
|
58
|
+
# @!scope class
|
59
|
+
# @return [Storage::Nodes::BaseStore] the Node storage instance
|
60
|
+
configure do |c|
|
61
|
+
c.logger = ::Logger.new($stdout)
|
62
|
+
|
63
|
+
c.after :set, :cru_path do
|
64
|
+
val = _get(:cru_path)
|
65
|
+
if val and !val.is_a?(Pathname)
|
66
|
+
_set(:cru_path, Pathname.new(val.to_s))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
c.forward :get, :site_store, Storage::Sites, :instance
|
71
|
+
c.forward :get, :node_store, Storage::Nodes, :instance
|
72
|
+
end
|
73
|
+
|
74
|
+
config.instance_exec do
|
75
|
+
def site_store=(args)
|
76
|
+
Storage::Sites.set_instance(*args)
|
77
|
+
end
|
78
|
+
def node_store=(args)
|
79
|
+
Storage::Nodes.set_instance(*args)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# @overload set_site_store(instance)
|
84
|
+
# @param [Storage::Sites::BaseStore] instance for the Site store
|
85
|
+
# @example Set the Site store
|
86
|
+
# Circuit.set_site_store Circuit::Storage::Sites::MongoidStore.new
|
87
|
+
# @overload set_site_store(klass)
|
88
|
+
# @param [Class] klass to create instance for the Site store
|
89
|
+
# @example Set the Site store
|
90
|
+
# Circuit.set_site_store Circuit::Storage::Sites::MongoidStore
|
91
|
+
# @overload set_site_store(symbol)
|
92
|
+
# @param [Symbol] symbol for a Site store class under Circuit::Storage::Sites
|
93
|
+
# @example Set the Site store
|
94
|
+
# Circuit.set_site_store :mongoid_store
|
95
|
+
# @return [Storage::Sites::BaseStore] the Site storage instance
|
96
|
+
# @see Storage.set_instance
|
97
|
+
def self.set_site_store(*args)
|
98
|
+
config.site_store = args
|
99
|
+
end
|
100
|
+
|
101
|
+
# @overload set_node_store(instance)
|
102
|
+
# @param [Storage::Nodes::BaseStore] instance for the Node store
|
103
|
+
# @example Set the Node store
|
104
|
+
# Circuit.set_node_store Circuit::Storage::Nodes::MongoidStore.new
|
105
|
+
# @overload set_node_store(klass)
|
106
|
+
# @param [Class] klass to create instance for the Node store
|
107
|
+
# @example Set the Node store
|
108
|
+
# Circuit.set_node_store Circuit::Storage::Nodes::MongoidStore
|
109
|
+
# @overload set_node_store(symbol)
|
110
|
+
# @param [Symbol] symbol for a Node store class under Circuit::Storage::Nodes
|
111
|
+
# @example Set the Node store
|
112
|
+
# Circuit.set_node_store :mongoid_store
|
113
|
+
# @return [Storage::Nodes::BaseStore] the Node storage instance
|
114
|
+
# @see Storage.set_instance
|
115
|
+
def self.set_node_store(*args)
|
116
|
+
config.node_store = args
|
117
|
+
end
|
118
|
+
|
119
|
+
# @return [Pathname] path to the vendor directory
|
120
|
+
def self.vendor_path
|
121
|
+
Pathname.new(__FILE__).expand_path.dirname.join("..", "vendor")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
Circuit::Compatibility.make_compatible
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Circuit
|
7
|
+
module Behavior
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
# Raised when the path for a rackup file is indeterminate.
|
11
|
+
class RackupPathError < Circuit::CircuitError; end
|
12
|
+
|
13
|
+
# @param [String] str name of Behavior constant to get
|
14
|
+
# @return [Behavior] Behavior constant
|
15
|
+
def self.get(str)
|
16
|
+
str.classify.constantize
|
17
|
+
rescue NameError
|
18
|
+
str = str.classify
|
19
|
+
nesting = str.deconstantize
|
20
|
+
nesting = (nesting.blank? ? Object : nesting.constantize)
|
21
|
+
|
22
|
+
mod = Module.new do
|
23
|
+
include Circuit::Behavior
|
24
|
+
self.cru_path = Circuit.cru_path.join(str.classify.underscore+".cru")
|
25
|
+
self.builder!
|
26
|
+
class_eval %(def self.to_s() "#{str}"; end)
|
27
|
+
end
|
28
|
+
nesting.const_set(str.demodulize, mod)
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
# Clones the builder into the subclass when using inheritance
|
33
|
+
def inherited(subclass)
|
34
|
+
subclass.builder = @builder.clone
|
35
|
+
end
|
36
|
+
|
37
|
+
# Indicates whether a Builder is defined or will be defined based on a rackup file
|
38
|
+
# @return [Boolean] false if there is no Builder and no rackup file to create one
|
39
|
+
def builder?
|
40
|
+
!!@builder or self.cru_path.file?
|
41
|
+
rescue RackupPathError
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
# Creates an empty Builder object or parses the rackup file if it exists
|
46
|
+
# @return [Builder] the Builder
|
47
|
+
def builder!
|
48
|
+
if self.cru_path.file?
|
49
|
+
@builder = Circuit::Rack::Builder.parse_file(self.cru_path)
|
50
|
+
else
|
51
|
+
@builder = Circuit::Rack::Builder.new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the Builder (and creates one if it doesn't exist yet)
|
56
|
+
# @return [Builder] the Builder
|
57
|
+
# @see #builder!
|
58
|
+
def builder
|
59
|
+
@builder ||= self.builder!
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_writer :builder
|
63
|
+
|
64
|
+
# @return [Pathname] the path to the rackup file
|
65
|
+
# @raise [RackupPathError] if the rackup file path is indeterminate
|
66
|
+
def cru_path
|
67
|
+
if @cru_path.nil? and Circuit.cru_path.nil?
|
68
|
+
raise RackupPathError, "Rackup path cannot be determined for #{self.to_s}"
|
69
|
+
end
|
70
|
+
@cru_path ||= Circuit.cru_path.join(self.class.to_s.underscore)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Sets the rackup file path and clears the #builder
|
74
|
+
# @param [Pathname,String] pathname of the rackup file
|
75
|
+
def cru_path=(pathname)
|
76
|
+
@cru_path = (pathname.is_a?(Pathname) ? pathname : Pathname.new(pathname.to_s))
|
77
|
+
self.builder = nil
|
78
|
+
end
|
79
|
+
|
80
|
+
# @!method use(middleware, *args, &block)
|
81
|
+
# @see http://rubydoc.info/gems/rack/Rack/Builder#use-instance_method
|
82
|
+
# ::Rack::Builder#use
|
83
|
+
|
84
|
+
# @!method run(app)
|
85
|
+
# @see http://rubydoc.info/gems/rack/Rack/Builder#run-instance_method
|
86
|
+
# ::Rack::Builder#run
|
87
|
+
|
88
|
+
# @!method map(path, &block)
|
89
|
+
# @see http://rubydoc.info/gems/rack/Rack/Builder#map-instance_method
|
90
|
+
# ::Rack::Builder#map
|
91
|
+
|
92
|
+
# @!method useto_app
|
93
|
+
# @see http://rubydoc.info/gems/rack/Rack/Builder#to_app-instance_method
|
94
|
+
# ::Rack::Builder#to_app
|
95
|
+
|
96
|
+
delegate :use, :run, :map, :to_app, :to => :builder
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|