radiant-vapor-extension 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +7 -0
- data/HELP_admin.md +37 -0
- data/LICENSE +20 -0
- data/README.rdoc +11 -0
- data/Rakefile +135 -0
- data/VERSION +1 -0
- data/app/controllers/admin/flow_meters_controller.rb +28 -0
- data/app/helpers/flow_meters_helper.rb +2 -0
- data/app/metal/vapor_flow.rb +59 -0
- data/app/models/flow_meter.rb +137 -0
- data/app/views/admin/flow_meters/index.html.haml +25 -0
- data/app/views/admin/help/_slug_redirect.html.haml +4 -0
- data/app/views/admin/pages/_node.html.haml +30 -0
- data/app/views/admin/pages/_vapor_details.html.haml +9 -0
- data/db/migrate/001_create_flow_meters.rb +15 -0
- data/lib/page_vapor.rb +12 -0
- data/lib/radiant-vapor-extension.rb +0 -0
- data/lib/tasks/vapor_extension_tasks.rake +28 -0
- data/lib/vaporizer.rb +71 -0
- data/spec/controllers/admin/flow_meters_controller_spec.rb +80 -0
- data/spec/metal/vapor_flow_spec.rb +28 -0
- data/spec/models/flow_meter_spec.rb +146 -0
- data/spec/models/page_spec.rb +18 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +37 -0
- data/test/radiant-vapor_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- data/vapor_extension.rb +37 -0
- metadata +99 -0
data/.document
ADDED
data/.gitignore
ADDED
data/HELP_admin.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
With Vapor you can create URLs that will point users to other locations.
|
2
|
+
|
3
|
+
## How It Works
|
4
|
+
|
5
|
+
Vapor manages the redirection in objects called flow meters. In each flow meter you'll need to have
|
6
|
+
the `catch_url` (which is the URL that will be the false page) and the `redirect_url` (which is an
|
7
|
+
actual page on your site). By default the `status` is set to '307 Temporarily Moved'.
|
8
|
+
|
9
|
+
You may also set the redirect_url to an external site beginning with 'http://'.
|
10
|
+
|
11
|
+
## What to Catch
|
12
|
+
|
13
|
+
You have some options with Vapor.
|
14
|
+
|
15
|
+
By default, each flow meter that you create will only match against
|
16
|
+
the exact url. This means that a `catch_url` of `/articles` will not redirect for a url of
|
17
|
+
`/articles/2008/09/19/third-post/`.
|
18
|
+
|
19
|
+
To change this, you may set `Radiant::Config['vapor.use_regexp'] = 'true'`. This will catch any url
|
20
|
+
that _begins_ with the given `catch_url`. The `catch_url` in this case is a regular expression, and
|
21
|
+
the `redirect_url` may contain substitution variables like $0 (the matched string), $1 (the first
|
22
|
+
match group), and so on.
|
23
|
+
|
24
|
+
You may also nest your flow meters with this setting. Setting `/about` to redirect to `/us` and `/about/team` to
|
25
|
+
redirect to `/team` will work. When the `vapor.use_regexp` option is set, the flow meters will be
|
26
|
+
compared to the requests in reverse alphabetical order so that longer `catch_url`s will be processed
|
27
|
+
first.
|
28
|
+
|
29
|
+
## Where and When
|
30
|
+
|
31
|
+
Vapor is a simple solution to allow your users to manage and edit URL redirection themselves. Long-term
|
32
|
+
redirects might be better served by addressing them outside of the application by handling the redirect
|
33
|
+
with your web or application server.
|
34
|
+
|
35
|
+
In order to prevent database access with each request to the site, Vapor loads all URL directives into
|
36
|
+
memory when the extension is initialized, when a new flow meter is created, and when a flow meter is
|
37
|
+
destroyed.
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Jim Gay
|
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 to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included 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
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
= Vapor
|
2
|
+
|
3
|
+
The Vapor extension provides an interface to redirect URLs.
|
4
|
+
|
5
|
+
Installing Vapor is as easy as any other Radiant extension. Drop it into your vendor/extensions directory and:
|
6
|
+
|
7
|
+
rake radiant:extensions:vapor:migrate
|
8
|
+
|
9
|
+
See the HELP_admin.md for more details.
|
10
|
+
|
11
|
+
built by Saturn Flyer http://www.saturnflyer.com
|
data/Rakefile
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |gem|
|
6
|
+
gem.name = "radiant-vapor-extension"
|
7
|
+
gem.summary = %Q{Provides an interface to redirect URLs in RadiantCMS}
|
8
|
+
gem.description = %Q{Provides an interface to redirect URLs in RadiantCMS}
|
9
|
+
gem.email = "jim@saturnflyer.com"
|
10
|
+
gem.homepage = "http://github.com/saturnflyer/radiant-vapor-extension"
|
11
|
+
gem.authors = ["Jim Gay"]
|
12
|
+
gem.add_development_dependency "radiant"
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
# task :test => :check_dependencies
|
20
|
+
|
21
|
+
# Determine where the RSpec plugin is by loading the boot
|
22
|
+
unless defined? RADIANT_ROOT
|
23
|
+
ENV["RAILS_ENV"] = "test"
|
24
|
+
case
|
25
|
+
when ENV["RADIANT_ENV_FILE"]
|
26
|
+
require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
|
27
|
+
when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
|
28
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
|
29
|
+
else
|
30
|
+
boot_path = "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
|
31
|
+
require boot_path if File.exist?(boot_path)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'rake'
|
36
|
+
require 'rake/rdoctask'
|
37
|
+
require 'rake/testtask'
|
38
|
+
|
39
|
+
if defined? RADIANT_ROOT
|
40
|
+
rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
|
41
|
+
$LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
|
42
|
+
end
|
43
|
+
|
44
|
+
require 'spec/rake/spectask'
|
45
|
+
|
46
|
+
# Cleanup the RADIANT_ROOT constant so specs will load the environment
|
47
|
+
Object.send(:remove_const, :RADIANT_ROOT) if defined? RADIANT_ROOT
|
48
|
+
|
49
|
+
extension_root = File.expand_path(File.dirname(__FILE__))
|
50
|
+
|
51
|
+
task :default => :spec
|
52
|
+
task :stats => "spec:statsetup"
|
53
|
+
|
54
|
+
desc "Run all specs in spec directory"
|
55
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
56
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
57
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
58
|
+
end
|
59
|
+
|
60
|
+
namespace :spec do
|
61
|
+
desc "Run all specs in spec directory with RCov"
|
62
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
63
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
64
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
65
|
+
t.rcov = true
|
66
|
+
t.rcov_opts = ['--exclude', 'spec', '--rails']
|
67
|
+
end
|
68
|
+
|
69
|
+
desc "Print Specdoc for all specs"
|
70
|
+
Spec::Rake::SpecTask.new(:doc) do |t|
|
71
|
+
t.spec_opts = ["--format", "specdoc", "--dry-run"]
|
72
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
73
|
+
end
|
74
|
+
|
75
|
+
[:models, :controllers, :views, :helpers].each do |sub|
|
76
|
+
desc "Run the specs under spec/#{sub}"
|
77
|
+
Spec::Rake::SpecTask.new(sub) do |t|
|
78
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
79
|
+
t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Setup specs for stats
|
84
|
+
task :statsetup do
|
85
|
+
require 'code_statistics'
|
86
|
+
::STATS_DIRECTORIES << %w(Model\ specs spec/models)
|
87
|
+
::STATS_DIRECTORIES << %w(View\ specs spec/views)
|
88
|
+
::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
|
89
|
+
::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
|
90
|
+
::CodeStatistics::TEST_TYPES << "Model specs"
|
91
|
+
::CodeStatistics::TEST_TYPES << "View specs"
|
92
|
+
::CodeStatistics::TEST_TYPES << "Controller specs"
|
93
|
+
::CodeStatistics::TEST_TYPES << "Helper specs"
|
94
|
+
::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
|
95
|
+
end
|
96
|
+
|
97
|
+
namespace :db do
|
98
|
+
namespace :fixtures do
|
99
|
+
desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
|
100
|
+
task :load => :environment do
|
101
|
+
require 'active_record/fixtures'
|
102
|
+
ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
|
103
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
|
104
|
+
Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
desc 'Generate documentation for the vapor extension.'
|
112
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
113
|
+
if File.exist?('VERSION')
|
114
|
+
version = File.read('VERSION')
|
115
|
+
else
|
116
|
+
version = ""
|
117
|
+
end
|
118
|
+
|
119
|
+
rdoc.rdoc_dir = 'rdoc'
|
120
|
+
rdoc.title = "Vapor Extension #{version}"
|
121
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
122
|
+
rdoc.rdoc_files.include('README')
|
123
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
124
|
+
end
|
125
|
+
|
126
|
+
# For extensions that are in transition
|
127
|
+
desc 'Test the vapor extension.'
|
128
|
+
Rake::TestTask.new(:test) do |t|
|
129
|
+
t.libs << 'lib'
|
130
|
+
t.pattern = 'test/**/*_test.rb'
|
131
|
+
t.verbose = true
|
132
|
+
end
|
133
|
+
|
134
|
+
# Load any custom rakefiles for extension
|
135
|
+
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.0
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Admin::FlowMetersController < ApplicationController
|
2
|
+
only_allow_access_to :index, :create, :destroy,
|
3
|
+
:when => :admin,
|
4
|
+
:denied_url => { :controller => 'pages', :action => 'index' },
|
5
|
+
:denied_message => 'You must be an administrator to manage Redirects.'
|
6
|
+
|
7
|
+
def index
|
8
|
+
@flow_meter = FlowMeter.new
|
9
|
+
@flow_meters = FlowMeter.find(:all)
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
@flow_meter = FlowMeter.create!(params[:flow_meter])
|
14
|
+
redirect_to admin_flow_meters_url
|
15
|
+
rescue ActiveRecord::RecordInvalid => e
|
16
|
+
flash[:error] = "#{e.message}"
|
17
|
+
redirect_to admin_flow_meters_url
|
18
|
+
rescue FlowMeter::DataMismatch => e
|
19
|
+
flash[:error] = "#{e.message}"
|
20
|
+
redirect_to admin_flow_meters_url
|
21
|
+
end
|
22
|
+
|
23
|
+
def destroy
|
24
|
+
@flow_meter = FlowMeter.find(params[:id])
|
25
|
+
@flow_meter.destroy
|
26
|
+
redirect_to admin_flow_meters_url
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
class VaporFlow
|
4
|
+
include Vaporizer
|
5
|
+
|
6
|
+
# Radiant must be restarted if the configuration changes for this setting
|
7
|
+
@@use_regexp = nil
|
8
|
+
class << self
|
9
|
+
def call(env)
|
10
|
+
if env["PATH_INFO"].blank?
|
11
|
+
return send_to_radiant
|
12
|
+
end
|
13
|
+
url = env["PATH_INFO"].sub(/^\//,'') #clean off the first slash, like it is stored in the db
|
14
|
+
db_escaped_key = ActiveRecord::Base.connection.adapter_name =~ /mysql/i ? '`key`' : 'key'
|
15
|
+
sql = "SELECT * FROM config where #{db_escaped_key} = 'vapor.use_regexp'"
|
16
|
+
if @@use_regexp.nil?
|
17
|
+
config_key = Radiant::Config.connection.select_one(sql)
|
18
|
+
@@use_regexp = (config_key && config_key['value'] == 'true') ? true : false
|
19
|
+
end
|
20
|
+
if @@use_regexp
|
21
|
+
catch_with_regexp(url)
|
22
|
+
else
|
23
|
+
catch_without_regexp(url)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def catch_with_regexp(url)
|
28
|
+
result = self.send_to_radiant
|
29
|
+
FlowMeter.all.sort.reverse.each do |meter|
|
30
|
+
key = meter[0]
|
31
|
+
value = meter[1]
|
32
|
+
if (match = url.match(Regexp.new('^'+key)))
|
33
|
+
status = value[1].to_i
|
34
|
+
redirect_url = self.match_substitute(value[0], match)
|
35
|
+
result = [status, {"Location" => CGI.unescape(local_or_external_path(redirect_url))}, [status.to_s]]
|
36
|
+
return result
|
37
|
+
break
|
38
|
+
end
|
39
|
+
end
|
40
|
+
return result
|
41
|
+
end
|
42
|
+
|
43
|
+
def catch_without_regexp(url)
|
44
|
+
url = url.sub(/\/$/, '') unless url == '/' # drop the trailing slash for lookup
|
45
|
+
a_match = FlowMeter.all[url]
|
46
|
+
unless a_match.nil?
|
47
|
+
status = a_match[1].to_i
|
48
|
+
redirect_url = a_match[0]
|
49
|
+
[status, {"Location" => CGI.unescape(local_or_external_path(redirect_url))}, [status.to_s]]
|
50
|
+
else
|
51
|
+
self.send_to_radiant
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def send_to_radiant
|
56
|
+
[404, {'Content-Type' => 'text/html'}, ['Off to Radiant we go!']]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
class FlowMeter < ActiveRecord::Base
|
2
|
+
class DataMismatch < StandardError; end
|
3
|
+
|
4
|
+
include Vaporizer
|
5
|
+
|
6
|
+
before_save :set_default_status
|
7
|
+
after_validation :clean_catch_url
|
8
|
+
after_validation :clean_redirect_url
|
9
|
+
after_save :initialize_all
|
10
|
+
after_destroy :initialize_all
|
11
|
+
|
12
|
+
validates_presence_of :catch_url, :on => :create, :message => "can't be blank"
|
13
|
+
validates_presence_of :redirect_url, :on => :create, :message => "can't be blank"
|
14
|
+
|
15
|
+
validates_uniqueness_of :catch_url
|
16
|
+
|
17
|
+
validate :catch_url_not_restricted
|
18
|
+
validate :redirect_url_not_restricted
|
19
|
+
|
20
|
+
@@all = {}
|
21
|
+
|
22
|
+
def self.all
|
23
|
+
@@all
|
24
|
+
end
|
25
|
+
|
26
|
+
def all
|
27
|
+
@@all
|
28
|
+
end
|
29
|
+
|
30
|
+
def all=(all_hash)
|
31
|
+
@@all = all_hash
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize_all
|
35
|
+
FlowMeter.initialize_all
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.initialize_all
|
39
|
+
@@all = {}
|
40
|
+
FlowMeter.find(:all).each do |fm|
|
41
|
+
@@all[fm[:catch_url]] = [fm[:redirect_url], fm[:status]]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def display_url(att)
|
46
|
+
path = self[att]
|
47
|
+
if path == '/'
|
48
|
+
'/'
|
49
|
+
elsif path.match('^https?://')
|
50
|
+
path
|
51
|
+
else
|
52
|
+
radiant_path(self.cleaned_up_path(path))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
[:catch_url, :redirect_url].each do |att|
|
57
|
+
define_method "#{att.to_s}_for_display" do
|
58
|
+
display_url(att)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def catch_url_not_restricted
|
63
|
+
if catch_url =~ %r{\A\/?(admin)}
|
64
|
+
errors.add(:catch_url, 'cannot catch the admin url')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def redirect_url_not_restricted
|
69
|
+
if catch_url == redirect_url
|
70
|
+
raise DataMismatch, "Catch URL and Redirect URL may not be the same."
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.find_for_page(page)
|
75
|
+
if Radiant::Config['vapor.use_regexp'] == 'true'
|
76
|
+
match = catch_url_match_with_regexp(page.url)
|
77
|
+
else
|
78
|
+
match = catch_url_match(page.url)
|
79
|
+
end
|
80
|
+
match = self.find_by_catch_url(match) if match
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.redirect_url_for_page(page)
|
84
|
+
if Radiant::Config['vapor.use_regexp'] == true
|
85
|
+
FlowMeter.match_for_page_with_regexp(page).to_s
|
86
|
+
else
|
87
|
+
FlowMeter.match_for_page(page).to_s
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def self.match_for_page(page)
|
94
|
+
url = page.url.sub(/\/$/, '') unless url == '/' # drop the trailing slash for lookup
|
95
|
+
url = url.sub(/^\//, '') unless url == '/'
|
96
|
+
a_match = FlowMeter.all[url]
|
97
|
+
unless a_match.nil?
|
98
|
+
redirect_url = a_match[0]
|
99
|
+
redirect_url = '/' + redirect_url unless redirect_url.match('^https?://') || redirect_url == '/'
|
100
|
+
return redirect_url
|
101
|
+
end
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.match_for_page_with_regexp(page)
|
106
|
+
redirect_url = nil
|
107
|
+
FlowMeter.all.sort.reverse.each do |meter|
|
108
|
+
key = meter[0]
|
109
|
+
value = meter[1]
|
110
|
+
if (match = url.match(Regexp.new('^'+key)))
|
111
|
+
redirect_url = match_substitute(value[0], match)
|
112
|
+
return redirect_url
|
113
|
+
break
|
114
|
+
end
|
115
|
+
end
|
116
|
+
redirect_url
|
117
|
+
end
|
118
|
+
|
119
|
+
def set_default_status
|
120
|
+
self.status = '307 Temporarily Moved' if self.status.blank?
|
121
|
+
end
|
122
|
+
|
123
|
+
def clean_catch_url
|
124
|
+
clean_url(:catch_url) unless catch_url.blank?
|
125
|
+
end
|
126
|
+
|
127
|
+
def clean_redirect_url
|
128
|
+
clean_url(:redirect_url) unless redirect_url.blank? or redirect_url.match('^http://')
|
129
|
+
end
|
130
|
+
|
131
|
+
def clean_url(att)
|
132
|
+
if !self[att].blank? and !self[att].nil?
|
133
|
+
path = self[att]
|
134
|
+
self.update_attribute(att, self.cleaned_up_path(path))
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
.outset
|
2
|
+
- form_for @flow_meter, :url => admin_flow_meters_path do |f|
|
3
|
+
%table.index
|
4
|
+
%thead
|
5
|
+
%tr
|
6
|
+
%th Catch URL
|
7
|
+
%th Redirect URL
|
8
|
+
%th Status
|
9
|
+
%th Action
|
10
|
+
%tbody
|
11
|
+
- @flow_meters.each do |flow_meter|
|
12
|
+
%tr
|
13
|
+
%td= flow_meter.catch_url_for_display
|
14
|
+
%td= flow_meter.redirect_url_for_display
|
15
|
+
%td= flow_meter.status
|
16
|
+
%td= link_to "Delete", admin_flow_meter_path(flow_meter), :method => :delete
|
17
|
+
%tr
|
18
|
+
%td= f.text_field :catch_url
|
19
|
+
%td= f.text_field :redirect_url
|
20
|
+
%td= f.select :status, ['307 Temporary Redirect','302 Found','301 Moved Permanently'].reverse
|
21
|
+
%td= submit_tag "Create"
|
22
|
+
%p With redirects you can create URLs that will point to content elsewhere on your site. Your 'Catch URL' is the part of the URL that will be processed to redirect to the final destination of your 'Redirect URL'.
|
23
|
+
- if config['vapor.use_regexp'] == 'true'
|
24
|
+
%p If the incoming request begins with any of your defined 'Catch URLs', the visitor will be redirected to the corresponding 'Redirect URL'. This means that you may protect an entire tree of your site simply by specifying the beginning of the URL.
|
25
|
+
%p You may use a full url for the 'Redirect URL' to direct your visitors to another site.
|
@@ -0,0 +1,4 @@
|
|
1
|
+
- admin_help do
|
2
|
+
%h4 Slugs and Redirects
|
3
|
+
%p= "You've got the Vapor extension installed which allows you to create false pages or false slugs. The #{link_to 'Redirects', admin_flow_meters_path} tab provides you with an area where you can create a slug, or url that will redirect your site visitors to another location."
|
4
|
+
%p So if you want your 'About Us' page to be found at yoursite.com/about and also at yoursite.com/about-us then you can create your page with 'about-us' as the slug, and create a redirect from '/about' to '/about-us'.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
%tr.node{:id => "page-#{page.id}", :class =>"level-#{level}#{children_class}#{virtual_class}"}
|
2
|
+
- render_region :node, :locals => {:page => page, :level => level, :simple => simple} do |node|
|
3
|
+
- node.title_column do
|
4
|
+
%td.page{:style => "padding-left: #{padding_left(level)}px"}
|
5
|
+
%span.w1
|
6
|
+
- if simple
|
7
|
+
= icon
|
8
|
+
= node_title
|
9
|
+
- else
|
10
|
+
= expander + link_to("#{icon} #{node_title}", edit_admin_page_url(page), :title => page.url)
|
11
|
+
= page_type
|
12
|
+
= spinner
|
13
|
+
- flow_meter = page.flow_meter
|
14
|
+
- if flow_meter
|
15
|
+
%small.info
|
16
|
+
Redirects to
|
17
|
+
= link_to flow_meter.redirect_url_for_display, flow_meter.redirect_url_for_display
|
18
|
+
- node.status_column do
|
19
|
+
- unless simple
|
20
|
+
%td.status{:class => "#{page.status.name.downcase}-status"}= page.status.name
|
21
|
+
- node.add_child_column do
|
22
|
+
- unless simple
|
23
|
+
%td.add-child= link_to image('add-child', :alt => 'add child'), new_admin_page_child_url(page)
|
24
|
+
- node.remove_column do
|
25
|
+
- unless simple
|
26
|
+
%td.remove= link_to image('remove', :alt => 'remove page'), remove_admin_page_url(page)
|
27
|
+
|
28
|
+
- if expanded
|
29
|
+
- page.children.each do |child|
|
30
|
+
= render_node child, :level => level + 1, :simple => simple
|
@@ -0,0 +1,9 @@
|
|
1
|
+
- if !@page.new_record? && (flow_meter = @page.flow_meter)
|
2
|
+
%p
|
3
|
+
Visitors to this page will redirected to
|
4
|
+
= link_to flow_meter.redirect_url_for_display, flow_meter.local_or_external_redirect_url
|
5
|
+
- if admin?
|
6
|
+
- unless config['vapor.use_regexp']
|
7
|
+
= link_to "Remove this", admin_flow_meter_path(flow_meter), :method => :delete
|
8
|
+
- else
|
9
|
+
= link_to "Manage your traffic flow...", admin_flow_meters_path
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateFlowMeters < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :flow_meters do |t|
|
4
|
+
t.string :catch_url
|
5
|
+
t.string :redirect_url
|
6
|
+
t.string :status, :default => '307'
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
drop_table :flow_meters
|
14
|
+
end
|
15
|
+
end
|
data/lib/page_vapor.rb
ADDED
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
namespace :radiant do
|
2
|
+
namespace :extensions do
|
3
|
+
namespace :vapor do
|
4
|
+
|
5
|
+
desc "Runs the migration of the Vapor extension"
|
6
|
+
task :migrate => :environment do
|
7
|
+
require 'radiant/extension_migrator'
|
8
|
+
if ENV["VERSION"]
|
9
|
+
VaporExtension.migrator.migrate(ENV["VERSION"].to_i)
|
10
|
+
else
|
11
|
+
VaporExtension.migrator.migrate
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Copies public assets of the Vapor to the instance public/ directory."
|
16
|
+
task :update => :environment do
|
17
|
+
is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
|
18
|
+
Dir[VaporExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
|
19
|
+
path = file.sub(VaporExtension.root, '')
|
20
|
+
directory = File.dirname(path)
|
21
|
+
puts "Copying #{path}..."
|
22
|
+
mkdir_p RAILS_ROOT + directory
|
23
|
+
cp file, RAILS_ROOT + path
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/vaporizer.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module Vaporizer
|
2
|
+
def self.included(klass)
|
3
|
+
klass.instance_eval do
|
4
|
+
extend ClassMethods
|
5
|
+
include InstanceMethods
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def catch_url_match_with_regexp(url)
|
11
|
+
result = nil
|
12
|
+
FlowMeter.all.sort.reverse.each do |meter|
|
13
|
+
prepared_url = cleaned_up_path(meter[0])
|
14
|
+
prepared_url = radiant_path(prepared_url)
|
15
|
+
if (match = url.match(Regexp.new('^'+prepared_url)))
|
16
|
+
return meter[0]
|
17
|
+
break
|
18
|
+
end
|
19
|
+
end
|
20
|
+
return result
|
21
|
+
end
|
22
|
+
|
23
|
+
def catch_url_match(url)
|
24
|
+
url = cleaned_up_path(url)
|
25
|
+
a_match = FlowMeter.all[url]
|
26
|
+
a_match ? url : nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def cleaned_up_path(path)
|
30
|
+
new_path = path.gsub(%r{//+},'/').gsub(%r{\s+},'')
|
31
|
+
new_path.gsub!(%r{\/$},'') unless new_path == '/'
|
32
|
+
new_path.gsub!(%r{^/},'') unless new_path == '/'
|
33
|
+
new_path
|
34
|
+
end
|
35
|
+
|
36
|
+
def radiant_path(path)
|
37
|
+
return path if path == '/'
|
38
|
+
'/' + path
|
39
|
+
end
|
40
|
+
|
41
|
+
def local_or_external_path(path)
|
42
|
+
path.match(/https?:\/\//) ? path : self.radiant_path(path)
|
43
|
+
end
|
44
|
+
|
45
|
+
def match_substitute(string, match)
|
46
|
+
string.gsub(/\$([`&0-9'$])/) do |sub|
|
47
|
+
case $1
|
48
|
+
when "`": match.pre_match
|
49
|
+
when "&": match[0]
|
50
|
+
when "0".."9": puts $1.to_i; match[$1.to_i]
|
51
|
+
when "'": match.post_match
|
52
|
+
when "$": '$'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
module InstanceMethods
|
59
|
+
def local_or_external_redirect_url
|
60
|
+
self.class.local_or_external_path(redirect_url)
|
61
|
+
end
|
62
|
+
|
63
|
+
def cleaned_up_path(path)
|
64
|
+
self.class.cleaned_up_path(path)
|
65
|
+
end
|
66
|
+
|
67
|
+
def radiant_path(path)
|
68
|
+
self.class.radiant_path(path)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Admin::FlowMetersController do
|
4
|
+
dataset :users
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
login_as :admin
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "/admin/flow_meters with GET" do
|
11
|
+
before(:each) do
|
12
|
+
@flow_meter = mock_model(FlowMeter)
|
13
|
+
@new_flow_meter = mock_model(FlowMeter)
|
14
|
+
@flow_meters = [@flow_meter]
|
15
|
+
FlowMeter.stub!(:find).with(:all).and_return(@flow_meters)
|
16
|
+
FlowMeter.stub!(:new).and_return(@new_flow_meter)
|
17
|
+
get :index
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should render the admin/index template" do
|
21
|
+
response.should render_template('index')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should get all flow_meters" do
|
25
|
+
assigns[:flow_meters].should == [@flow_meter]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should get a new flow_meter" do
|
29
|
+
assigns[:flow_meter].should == @new_flow_meter
|
30
|
+
end
|
31
|
+
end
|
32
|
+
describe "/admin/flow_meters with valid POST" do
|
33
|
+
before(:each) do
|
34
|
+
@flow_meter = FlowMeter.create!(:catch_url => 'this', :redirect_url => 'that', :status => '302 Found')
|
35
|
+
@flow_meter_count = FlowMeter.count
|
36
|
+
post :create, :flow_meter => {:catch_url => 'other', :redirect_url => 'that'}
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should increase the flow_meter_count by 1" do
|
40
|
+
FlowMeter.count.should > @flow_meter_count
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should redirect to the index" do
|
44
|
+
response.should redirect_to('/admin/flow_meters')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
describe "/admin/flow_meters with invalid POST" do
|
48
|
+
before(:each) do
|
49
|
+
post :create, :flow_meter => {:catch_url => 'admin', :redirect_url => 'that'}
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should assign the error message to the flash" do
|
53
|
+
flash[:error].should_not be_blank
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should redirect to the index" do
|
57
|
+
response.should redirect_to('/admin/flow_meters')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
describe "/admin/flow_meters/:id with DELETE" do
|
61
|
+
before(:each) do
|
62
|
+
@flow_meter = FlowMeter.create!(:catch_url => 'this', :redirect_url => 'that', :status => '302 Found')
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should find the flow_meter" do
|
66
|
+
FlowMeter.stub!(:find).with(:all).and_return([@flow_meter])
|
67
|
+
FlowMeter.should_receive(:find).with(@flow_meter.id.to_s).and_return(@flow_meter)
|
68
|
+
delete :destroy, :id => @flow_meter.id
|
69
|
+
end
|
70
|
+
it "should reduce the flow_meter count by 1" do
|
71
|
+
@flow_meter_count = FlowMeter.count
|
72
|
+
delete :destroy, :id => @flow_meter.id
|
73
|
+
FlowMeter.count.should < @flow_meter_count
|
74
|
+
end
|
75
|
+
it "should redirect to the index" do
|
76
|
+
delete :destroy, :id => @flow_meter.id
|
77
|
+
response.should redirect_to('/admin/flow_meters')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe VaporFlow do
|
4
|
+
describe "radiant_path" do
|
5
|
+
it "should return the given path prepended with a /" do
|
6
|
+
VaporFlow.radiant_path('slashy').should == '/slashy'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
describe "local_or_external_path" do
|
10
|
+
it "should return the given path if it begins with 'http'" do
|
11
|
+
VaporFlow.local_or_external_path('http://saturnflyer.com').should == 'http://saturnflyer.com'
|
12
|
+
end
|
13
|
+
it "should return the given path if it begins with 'https'" do
|
14
|
+
VaporFlow.local_or_external_path('https://saturnflyer.com').should == 'https://saturnflyer.com'
|
15
|
+
end
|
16
|
+
it "should return the radiant_path if the given path does not begin with http" do
|
17
|
+
VaporFlow.local_or_external_path('about/the/site').should == VaporFlow.radiant_path('about/the/site')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
describe "send_to_radiant" do
|
21
|
+
it "should return an array" do
|
22
|
+
VaporFlow.send_to_radiant.kind_of?(Array).should be_true
|
23
|
+
end
|
24
|
+
it "should have 404 as the first item in the array" do
|
25
|
+
VaporFlow.send_to_radiant.first.should == 404
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe FlowMeter do
|
4
|
+
dataset :pages
|
5
|
+
before(:each) do
|
6
|
+
# FlowMeter.all = {}
|
7
|
+
@flow_meter = FlowMeter.new(:catch_url => "/stuff", :redirect_url => '/things', :status => '')
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should err without a catch_url" do
|
11
|
+
@flow_meter.catch_url = nil
|
12
|
+
@flow_meter.valid?
|
13
|
+
@flow_meter.errors.on(:catch_url).should match(/can't be blank/)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should err without a redirect_url" do
|
17
|
+
@flow_meter.redirect_url = nil
|
18
|
+
@flow_meter.valid?
|
19
|
+
@flow_meter.errors.on(:redirect_url).should match(/can't be blank/)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should set '307 Temporarily Moved' as the status if created with no status" do
|
23
|
+
@flow_meter.save!
|
24
|
+
@flow_meter.status.should == '307 Temporarily Moved'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should err with a catch_url beginning with 'admin'" do
|
28
|
+
@flow_meter.catch_url = "admin"
|
29
|
+
@flow_meter.valid?
|
30
|
+
@flow_meter.errors.on(:catch_url).should match(/cannot catch the admin url/)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should err with a catch_url beginning with '/admin'" do
|
34
|
+
@flow_meter.catch_url = "/admin"
|
35
|
+
@flow_meter.valid?
|
36
|
+
@flow_meter.errors.on(:catch_url).should match(/cannot catch the admin url/)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should err with a non-unique catch_url" do
|
40
|
+
@flow_meter.save
|
41
|
+
@flow_meter2 = FlowMeter.new(:catch_url => @flow_meter.catch_url, :redirect_url => '/other')
|
42
|
+
@flow_meter2.valid?
|
43
|
+
@flow_meter2.errors.on(:catch_url).should match(/has already been taken/)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should remove the first character from catch_url beginning with a slash" do
|
47
|
+
@flow_meter.save
|
48
|
+
@flow_meter.catch_url.should == 'stuff'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should remove the first character from redirect_url beginning with a slash" do
|
52
|
+
@flow_meter.save
|
53
|
+
@flow_meter.redirect_url.should == 'things'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should remove consecutive slashes from the catch_url before saving" do
|
57
|
+
@flow_meter.catch_url = "///slasher"
|
58
|
+
@flow_meter.save
|
59
|
+
@flow_meter.catch_url.should == 'slasher'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should remove consecutive slashes from the redirect_url before saving" do
|
63
|
+
@flow_meter.redirect_url = "///chop"
|
64
|
+
@flow_meter.save
|
65
|
+
@flow_meter.redirect_url.should == 'chop'
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should remove a trailing slash from the catch_url before saving" do
|
69
|
+
@flow_meter.catch_url = '/no_trailing_slash/'
|
70
|
+
@flow_meter.save
|
71
|
+
@flow_meter.catch_url.should == 'no_trailing_slash'
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should remove all whitespace from catch_url before saving" do
|
75
|
+
@flow_meter.catch_url = "hello there"
|
76
|
+
@flow_meter.save
|
77
|
+
@flow_meter.catch_url.should == 'hellothere'
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should remove all whitespace from redirect_url before saving" do
|
81
|
+
@flow_meter.redirect_url = "how are you"
|
82
|
+
@flow_meter.save
|
83
|
+
@flow_meter.redirect_url.should == 'howareyou'
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should allow '/' as the redirect_url" do
|
87
|
+
@flow_meter.redirect_url = "/"
|
88
|
+
@flow_meter.save
|
89
|
+
@flow_meter.redirect_url.should == '/'
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should allow a redirect_url formatted like 'http://www.saturnflyer.com/'" do
|
93
|
+
@flow_meter.redirect_url = 'http://www.saturnflyer.com/'
|
94
|
+
@flow_meter.save!
|
95
|
+
@flow_meter.redirect_url.should == 'http://www.saturnflyer.com/'
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should provide a catch_url_for_display which includes a leading slash" do
|
99
|
+
@flow_meter.catch_url_for_display.should == '/stuff'
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should provide a redirect_url_for_display which includes a leading slash" do
|
103
|
+
@flow_meter.redirect_url_for_display.should == '/things'
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should provide the actual redirect_url_for_display if it begins with 'http://'" do
|
107
|
+
@flow_meter.redirect_url = "http://www.saturnflyer.com"
|
108
|
+
@flow_meter.redirect_url_for_display.should == "http://www.saturnflyer.com"
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should err with 'Catch URL and Redirect URL may not be the same.' when given a catch_url that matches the redirect_url" do
|
112
|
+
@flow_meter.redirect_url = "/stuff"
|
113
|
+
lambda {@flow_meter.save!}.should raise_error(FlowMeter::DataMismatch, "Catch URL and Redirect URL may not be the same.")
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should load save all flow_meters into FlowMeter.all, a Hash with the catch_url as the key, and an array of redirect_url and status as the value" do
|
117
|
+
FlowMeter.destroy_all
|
118
|
+
@flow_meter.save
|
119
|
+
FlowMeter.all.should == {'stuff' => ['things', '307 Temporarily Moved']}
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should reload FlowMeter.all after destroying a flow_meter" do
|
123
|
+
@flow_meter.save
|
124
|
+
@flow_meter2 = FlowMeter.new(:catch_url => 'old', :redirect_url => 'new')
|
125
|
+
@flow_meter2.save
|
126
|
+
@flow_meter.destroy
|
127
|
+
FlowMeter.all.should == {'old' => ['new', '307']}
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "self.find_for_page" do
|
131
|
+
it "should return nil if no flow_meter matches for the page" do
|
132
|
+
FlowMeter.find_for_page(pages(:home)).should be_nil
|
133
|
+
end
|
134
|
+
it "should return the first flow_meter found that matches the page url" do
|
135
|
+
@redirector = FlowMeter.create!({:catch_url => '/first', :redirect_url => '/another', :status => '307'})
|
136
|
+
FlowMeter.find_for_page(pages(:first)).should == @redirector
|
137
|
+
end
|
138
|
+
describe "while vapor.use_regexp" do
|
139
|
+
it "should return the first flow_meter found that matches the page url" do
|
140
|
+
Radiant::Config['vapor.use_regexp'] = 'true'
|
141
|
+
@redirector = FlowMeter.create!({:catch_url => '/fi\w', :redirect_url => '/another', :status => '307'})
|
142
|
+
FlowMeter.find_for_page(pages(:first)).should == @redirector
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Page do
|
4
|
+
dataset :users_and_pages
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@redirector = FlowMeter.create!({:catch_url => '/first', :redirect_url => '/another', :status => '307'})
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'flow_meter' do
|
11
|
+
it "should return nil if none is found" do
|
12
|
+
pages(:home).flow_meter.should be_nil
|
13
|
+
end
|
14
|
+
it "should return the first flow_meter found which matches the page url" do
|
15
|
+
pages(:first).flow_meter.should == @redirector
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
unless defined? RADIANT_ROOT
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
3
|
+
case
|
4
|
+
when ENV["RADIANT_ENV_FILE"]
|
5
|
+
require ENV["RADIANT_ENV_FILE"]
|
6
|
+
when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
|
7
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../../")}/config/environment"
|
8
|
+
else
|
9
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../")}/config/environment"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
require "#{RADIANT_ROOT}/spec/spec_helper"
|
13
|
+
|
14
|
+
if File.directory?(File.dirname(__FILE__) + "/scenarios")
|
15
|
+
Scenario.load_paths.unshift File.dirname(__FILE__) + "/scenarios"
|
16
|
+
end
|
17
|
+
if File.directory?(File.dirname(__FILE__) + "/matchers")
|
18
|
+
Dir[File.dirname(__FILE__) + "/matchers/*.rb"].each {|file| require file }
|
19
|
+
end
|
20
|
+
|
21
|
+
Spec::Runner.configure do |config|
|
22
|
+
# config.use_transactional_fixtures = true
|
23
|
+
# config.use_instantiated_fixtures = false
|
24
|
+
# config.fixture_path = RAILS_ROOT + '/spec/fixtures'
|
25
|
+
|
26
|
+
# You can declare fixtures for each behaviour like this:
|
27
|
+
# describe "...." do
|
28
|
+
# fixtures :table_a, :table_b
|
29
|
+
#
|
30
|
+
# Alternatively, if you prefer to declare them only once, you can
|
31
|
+
# do so here, like so ...
|
32
|
+
#
|
33
|
+
# config.global_fixtures = :table_a, :table_b
|
34
|
+
#
|
35
|
+
# If you declare global fixtures, be aware that they will be declared
|
36
|
+
# for all of your examples, even those that don't use them.
|
37
|
+
end
|
data/test/test_helper.rb
ADDED
data/vapor_extension.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require_dependency 'application_controller'
|
2
|
+
|
3
|
+
class VaporExtension < Radiant::Extension
|
4
|
+
version "#{File.read(File.expand_path(File.dirname(__FILE__)) + '/VERSION')}"
|
5
|
+
description "Manage redirects without creating useless pages"
|
6
|
+
url "http://saturnflyer.com/"
|
7
|
+
|
8
|
+
define_routes do |map|
|
9
|
+
map.namespace :admin do |admin|
|
10
|
+
admin.resources 'flow_meters', :only => [:index, :create, :destroy]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def activate
|
15
|
+
unless respond_to?(:tab)
|
16
|
+
admin.tabs.add "Redirects", "/admin/flow_meters", :after => "Layouts", :visibility => [:admin]
|
17
|
+
else
|
18
|
+
tab 'Content' do
|
19
|
+
add_item 'Redirects', '/admin/flow_meters'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
FlowMeter.initialize_all if ActiveRecord::Base.connection.tables.include?('flow_meters')
|
23
|
+
|
24
|
+
Page.class_eval { include PageVapor }
|
25
|
+
|
26
|
+
admin.pages.edit.add :form, 'vapor_details', :before => 'edit_title'
|
27
|
+
|
28
|
+
if admin.respond_to? :help
|
29
|
+
admin.help.index.add :page_details, 'slug_redirect', :after => 'slug'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def deactivate
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: radiant-vapor-extension
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jim Gay
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-04 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: radiant
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: Provides an interface to redirect URLs in RadiantCMS
|
26
|
+
email: jim@saturnflyer.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- LICENSE
|
33
|
+
- README.rdoc
|
34
|
+
files:
|
35
|
+
- .document
|
36
|
+
- .gitignore
|
37
|
+
- HELP_admin.md
|
38
|
+
- LICENSE
|
39
|
+
- README.rdoc
|
40
|
+
- Rakefile
|
41
|
+
- VERSION
|
42
|
+
- app/controllers/admin/flow_meters_controller.rb
|
43
|
+
- app/helpers/flow_meters_helper.rb
|
44
|
+
- app/metal/vapor_flow.rb
|
45
|
+
- app/models/flow_meter.rb
|
46
|
+
- app/views/admin/flow_meters/index.html.haml
|
47
|
+
- app/views/admin/help/_slug_redirect.html.haml
|
48
|
+
- app/views/admin/pages/_node.html.haml
|
49
|
+
- app/views/admin/pages/_vapor_details.html.haml
|
50
|
+
- db/migrate/001_create_flow_meters.rb
|
51
|
+
- lib/page_vapor.rb
|
52
|
+
- lib/radiant-vapor-extension.rb
|
53
|
+
- lib/tasks/vapor_extension_tasks.rake
|
54
|
+
- lib/vaporizer.rb
|
55
|
+
- spec/controllers/admin/flow_meters_controller_spec.rb
|
56
|
+
- spec/metal/vapor_flow_spec.rb
|
57
|
+
- spec/models/flow_meter_spec.rb
|
58
|
+
- spec/models/page_spec.rb
|
59
|
+
- spec/spec.opts
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
- test/radiant-vapor_test.rb
|
62
|
+
- test/test_helper.rb
|
63
|
+
- vapor_extension.rb
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://github.com/saturnflyer/radiant-vapor-extension
|
66
|
+
licenses: []
|
67
|
+
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options:
|
70
|
+
- --charset=UTF-8
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.5
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Provides an interface to redirect URLs in RadiantCMS
|
92
|
+
test_files:
|
93
|
+
- spec/controllers/admin/flow_meters_controller_spec.rb
|
94
|
+
- spec/metal/vapor_flow_spec.rb
|
95
|
+
- spec/models/flow_meter_spec.rb
|
96
|
+
- spec/models/page_spec.rb
|
97
|
+
- spec/spec_helper.rb
|
98
|
+
- test/radiant-vapor_test.rb
|
99
|
+
- test/test_helper.rb
|