locomotive_plugins 1.0.0.beta6 → 1.0.0.beta7

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/CHANGELOG CHANGED
@@ -5,6 +5,7 @@
5
5
  * Removed content type scoping (use liquid tags instead)
6
6
  * Removed DBModels (just use Mongoid and LocomotiveCMS will isolate the models)
7
7
  * Added class tracking (used by Locomotive)
8
+ * Added ability to supply a rack app for handling requests
8
9
 
9
10
  ## v0.2.1
10
11
 
data/README.md CHANGED
@@ -279,3 +279,14 @@ comes in to site A which causes a Mongoid Document to be saved to the database,
279
279
  this document will not be accessible to the plugin when a request comes in to
280
280
  site B. Thus plugin database models should be developed in the context of a
281
281
  single site, since each site will have its own database.
282
+
283
+ ### Rack App
284
+
285
+ Plugins can supply a Rack Application to be used for request handling. Do so by
286
+ overriding the `rack_app` class method on the plugin class. The plugin object
287
+ can also build URLs and paths for that Rack App without knowledge of where it
288
+ is mounted. This is important because Locomotive will mount the rack
289
+ application on a path based on the plugin's `plugin_id`. Given a string `path`
290
+ which is a path relative to the root of the rack app,
291
+ `plugin_object.full_path(path)` will give the full absolute path and
292
+ `plugin_object.full_url(path)` will give the full URL.
@@ -13,6 +13,7 @@ module Locomotive
13
13
  include ClassTracker
14
14
  include ConfigUI
15
15
  include Liquid
16
+ include RackAppHelpers
16
17
 
17
18
  # @private
18
19
  #
@@ -21,7 +22,8 @@ module Locomotive
21
22
  #
22
23
  # @param base the plugin class
23
24
  def self.included(base)
24
- self.add_liquid_tag_methods(base)
25
+ self.add_liquid_class_methods(base)
26
+ self.add_rack_app_helper_methods(base)
25
27
 
26
28
  base.class_eval do
27
29
  extend ActiveModel::Callbacks
@@ -74,6 +76,14 @@ module Locomotive
74
76
  def liquid_tags
75
77
  {}
76
78
  end
79
+
80
+ # Override this method to supply a rack app to be used for handling
81
+ # requests. Locomotive CMS will mount this app on a path dependent on the
82
+ # `plugin_id`. See `RackAppHelpers` for some helper methods.
83
+ def rack_app
84
+ nil
85
+ end
86
+
77
87
  end
78
88
 
79
89
  # This variable is set by LocomotiveCMS. It contains the controller which
@@ -0,0 +1,9 @@
1
+
2
+ module Locomotive
3
+ module Plugin
4
+
5
+ # General Locomotive::Plugin exception
6
+ class Error < StandardError; end
7
+
8
+ end
9
+ end
@@ -18,7 +18,7 @@ module Locomotive
18
18
  # Adds methods from LiquidClassMethods module.
19
19
  #
20
20
  # @param base the plugin class to extend LiquidClassMethods
21
- def add_liquid_tag_methods(base)
21
+ def add_liquid_class_methods(base)
22
22
  base.extend(LiquidClassMethods)
23
23
  end
24
24
  end
@@ -0,0 +1,92 @@
1
+
2
+ module Locomotive
3
+ module Plugin
4
+ # This module adds helpers for handling the Rack app supplied by the
5
+ # `rack_app` method.
6
+ module RackAppHelpers
7
+
8
+ # @private
9
+ #
10
+ # Add class methods.
11
+ #
12
+ # @param base the class which includes this module
13
+ def self.included(base)
14
+ base.extend(ClassMethods)
15
+ end
16
+
17
+ # @api internal
18
+ module ClassMethods
19
+ # Adds methods from RackAppHelpersClassMethods module.
20
+ #
21
+ # @param base the plugin class to extend LiquidClassMethods
22
+ def add_rack_app_helper_methods(base)
23
+ base.extend(RackAppHelpersClassMethods)
24
+ end
25
+ end
26
+
27
+ # This module adds class methods for managing the mount point for the
28
+ # Rack App. The mount point must be set in order to properly generate
29
+ # paths and URLs.
30
+ module RackAppHelpersClassMethods
31
+ # Set the full URL mountpoint for the Rack app. This will be set by
32
+ # Locomotive CMS. The URL must be an HTTP or HTTPS url with no query
33
+ # parameters or hash fragments.
34
+ #
35
+ # @param url [String] the full URL that the Rack app is mounted on
36
+ def set_mountpoint(url)
37
+ error = lambda do |msg|
38
+ raise Error, "Invalid mountpoint: #{msg}"
39
+ end
40
+
41
+ uri = URI(url)
42
+ unless uri.scheme =~ /^https?$/
43
+ error.call('only http or https allowed')
44
+ end
45
+ if uri.fragment
46
+ error.call('no hash fragment allowed')
47
+ end
48
+ if uri.query
49
+ error.call('no query string allowed')
50
+ end
51
+
52
+ @mountpoint = uri
53
+ end
54
+
55
+ # Get the mountpoint for this plugin class's Rack app.
56
+ #
57
+ # @return the mountpoint
58
+ def mountpoint
59
+ @mountpoint
60
+ end
61
+ end
62
+
63
+ # Generate the full absolute path for the given path based on the
64
+ # mountpoint of this plugin's rack app.
65
+ #
66
+ # @param path [String] the path relative to the mountpoint of the rack
67
+ # app
68
+ # @return the absolute path
69
+ def full_path(path)
70
+ [ mountpoint.path.sub(%r{/+$}, ''), path.sub(%r{^/+}, '') ].join('/')
71
+ end
72
+
73
+ # Generate the full URL for the given path based on the mountpoint of
74
+ # this plugin's rack app.
75
+ #
76
+ # @param path [String] the path relative to the mountpoint of the rack
77
+ # app
78
+ # @return the URL
79
+ def full_url(path)
80
+ [ mountpoint.to_s.sub(%r{/+$}, ''), path.sub(%r{^/+}, '') ].join('/')
81
+ end
82
+
83
+ # Get the mountpoint for this plugin's Rack app.
84
+ #
85
+ # @return the mountpoint
86
+ def mountpoint
87
+ self.class.mountpoint
88
+ end
89
+
90
+ end
91
+ end
92
+ end
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LocomotivePlugins
2
- VERSION = '1.0.0.beta6'
2
+ VERSION = '1.0.0.beta7'
3
3
  end
@@ -0,0 +1,66 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ module Locomotive
5
+ module Plugin
6
+ describe RackAppHelpers do
7
+
8
+ before(:all) do
9
+ PluginWithRackApp.set_mountpoint('http://www.example.com/my/path')
10
+ end
11
+
12
+ before(:each) do
13
+ @config = {}
14
+ @plugin = PluginWithRackApp.new(@config)
15
+ end
16
+
17
+ it 'should supply an absolute path based on where it is mounted' do
18
+ @plugin.full_path('/plugin/path').should == '/my/path/plugin/path'
19
+ @plugin.full_path('another//path').should == '/my/path/another//path'
20
+ end
21
+
22
+ it 'should supply a full URL based on where it is mounted' do
23
+ @plugin.full_url('/plugin/path').should ==
24
+ 'http://www.example.com/my/path/plugin/path'
25
+ @plugin.full_url('another//path').should ==
26
+ 'http://www.example.com/my/path/another//path'
27
+ end
28
+
29
+ it 'should only allow URLs with proper format' do
30
+ old_mountpoint = PluginWithRackApp.mountpoint
31
+
32
+ bad_mountpoints = [
33
+ 'my/path',
34
+ 'my.server.com/my/path',
35
+ 'ftp://my.server.com',
36
+ 'http://my.server.com/my/path?q=value',
37
+ 'http://my.server.com/my/path#fragment',
38
+ 'https://my.server.com/my/path?q=value',
39
+ 'https://my.server.com/my/path#fragment'
40
+ ]
41
+
42
+ good_mountpoints = [
43
+ 'http://my.server.com/my/path',
44
+ 'http://my.server.com:3000/my/path',
45
+ 'https://my.server.com/my/path',
46
+ 'https://my.server.com:3000/my/path'
47
+ ]
48
+
49
+ bad_mountpoints.each do |mountpoint|
50
+ lambda do
51
+ PluginWithRackApp.set_mountpoint(mountpoint)
52
+ end.should raise_exception(Locomotive::Plugin::Error)
53
+ PluginWithRackApp.mountpoint.should == old_mountpoint
54
+ end
55
+
56
+ good_mountpoints.each do |mountpoint|
57
+ lambda do
58
+ PluginWithRackApp.set_mountpoint(mountpoint)
59
+ end.should_not raise_exception
60
+ PluginWithRackApp.mountpoint.to_s.should == mountpoint
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -47,5 +47,10 @@ module Locomotive
47
47
  }
48
48
  end
49
49
 
50
+ it 'should optionally supply a Rack application' do
51
+ UselessPlugin.rack_app.should be_nil
52
+ PluginWithRackApp.rack_app.should_not be_nil
53
+ end
54
+
50
55
  end
51
56
  end
@@ -0,0 +1,10 @@
1
+
2
+ class PluginWithRackApp
3
+ include Locomotive::Plugin
4
+
5
+ def self.rack_app
6
+ Proc.new do
7
+ [200, {'Content-Type' => 'text/html'}, []]
8
+ end
9
+ end
10
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: locomotive_plugins
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta6
4
+ version: 1.0.0.beta7
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-17 00:00:00.000000000 Z
12
+ date: 2013-01-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: locomotive_liquid
@@ -117,10 +117,12 @@ files:
117
117
  - Rakefile
118
118
  - lib/locomotive/plugin/liquid.rb
119
119
  - lib/locomotive/plugin/class_tracker.rb
120
+ - lib/locomotive/plugin/exceptions.rb
120
121
  - lib/locomotive/plugin/liquid/prefixed_filter_module.rb
121
122
  - lib/locomotive/plugin/liquid/drop_extension.rb
122
123
  - lib/locomotive/plugin/liquid/tag_subclass_methods.rb
123
124
  - lib/locomotive/plugin/liquid/context_helpers.rb
125
+ - lib/locomotive/plugin/rack_app_helpers.rb
124
126
  - lib/locomotive/plugin/config_ui.rb
125
127
  - lib/locomotive/plugin.rb
126
128
  - lib/version.rb
@@ -133,10 +135,12 @@ files:
133
135
  - spec/support/plugins/plugin_with_filter.rb
134
136
  - spec/support/plugins/plugin_with_many_filter_modules.rb
135
137
  - spec/support/plugins/my_plugin.rb
138
+ - spec/support/plugins/plugin_with_rack_app.rb
136
139
  - spec/support/factories.rb
137
140
  - spec/fixtures/config_template.haml
138
141
  - spec/fixtures/config_template.html
139
142
  - spec/lib/locomotive/plugin/class_tracker_spec.rb
143
+ - spec/lib/locomotive/plugin/rack_app_helpers_spec.rb
140
144
  - spec/lib/locomotive/plugin/liquid/context_helpers_spec.rb
141
145
  - spec/lib/locomotive/plugin/liquid_spec.rb
142
146
  - spec/lib/locomotive/plugin/config_ui_spec.rb