circuit 0.2.0
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.
- 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
|
+
[](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
|