lurker 0.6.12 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rspec +1 -2
- data/.travis.yml +30 -20
- data/Gemfile +0 -32
- data/README.md +14 -52
- data/Rakefile +3 -3
- data/cucumber.yml +1 -2
- data/features/atom_persistent_within_the_same_type.feature +4 -4
- data/features/controller_nested_schema_scaffolding.feature +7 -10
- data/features/controller_schema_scaffolding.feature +1 -3
- data/features/dereferencing_through_inlining.feature +1 -3
- data/features/html_generation.feature +3 -4
- data/features/minitest.feature +3 -5
- data/features/multidomain_support.feature +5 -6
- data/features/multitype_request_support.feature +1 -3
- data/features/partials.feature +3 -5
- data/features/request_nested_schema_scaffolding.feature +0 -2
- data/features/request_schema_scaffolding.feature +0 -2
- data/features/schema_suffixes.feature +2 -6
- data/features/schema_updating_within_test_suite.feature +2 -6
- data/features/step_definitions/additional_cli_steps.rb +8 -11
- data/features/support/env.rb +50 -10
- data/features/test_endpoint.feature +2 -6
- data/gemfiles/rails_4.gemfile +14 -0
- data/gemfiles/rails_5.gemfile +10 -0
- data/gemfiles/rails_6.gemfile +10 -0
- data/lib/lurker.rb +0 -1
- data/lib/lurker/cli.rb +5 -7
- data/lib/lurker/endpoint.rb +4 -4
- data/lib/lurker/json/concerns/validatable.rb +5 -1
- data/lib/lurker/json/parser.rb +1 -1
- data/lib/lurker/presenters/service_presenter.rb +2 -1
- data/lib/lurker/spec_helper/rspec.rb +0 -4
- data/lib/lurker/spy.rb +3 -1
- data/lib/lurker/templates/public/application.css +3 -3
- data/lib/lurker/templates/public/application.js +13 -2896
- data/lib/lurker/version.rb +1 -1
- data/lurker.gemspec +31 -33
- data/spec/spec_helper.rb +0 -1
- data/tasks/build.rake +5 -3
- data/tasks/generate.rake +25 -15
- data/templates/Dockerfile +26 -0
- data/templates/generate_stuff.rb +59 -26
- data/templates/lurker_app.rb +27 -47
- data/templates/rails4_ruby26_thread_error_fix.rb +20 -0
- metadata +136 -98
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -3
- data/Appraisals +0 -36
- data/gemfiles/rails_32.gemfile +0 -31
- data/gemfiles/rails_40.gemfile +0 -31
- data/gemfiles/rails_41.gemfile +0 -31
- data/gemfiles/rails_42.gemfile +0 -31
- data/lib/lurker/validation_error.rb +0 -4
- data/templates/rails32_http_patch_support.rb +0 -125
- metadata.gz.sig +0 -0
@@ -60,8 +60,6 @@ Feature: multitype request support
|
|
60
60
|
Scenario: json schema tests response parameters and update request parameters using "users/update"
|
61
61
|
Given a file named "spec/controllers/api/v2/users_controller_spec.rb" with:
|
62
62
|
"""ruby
|
63
|
-
require "spec_helper"
|
64
|
-
|
65
63
|
describe Api::V2::UsersController, :lurker do
|
66
64
|
render_views
|
67
65
|
|
@@ -70,7 +68,7 @@ Feature: multitype request support
|
|
70
68
|
end
|
71
69
|
|
72
70
|
it "updates a user surname as string" do
|
73
|
-
patch :update, id: user.id, user: { surname: 'Marley' }
|
71
|
+
patch :update, params: { id: user.id, user: { surname: 'Marley' } }
|
74
72
|
expect(response).to be_success
|
75
73
|
end
|
76
74
|
end
|
data/features/partials.feature
CHANGED
@@ -65,8 +65,6 @@ Feature: partials
|
|
65
65
|
|
66
66
|
Given a file named "spec/requests/repo_creation_spec.rb" with:
|
67
67
|
"""ruby
|
68
|
-
require "spec_helper"
|
69
|
-
|
70
68
|
describe Api::V1::ReposController, :lurker do
|
71
69
|
let!(:user) do
|
72
70
|
User.where(name: 'razum2um').first_or_create!
|
@@ -74,7 +72,7 @@ Feature: partials
|
|
74
72
|
|
75
73
|
it "creates a new repo" do
|
76
74
|
expect {
|
77
|
-
post "/api/v1/users/#{user.id}/repos.json", repo: { name: 'new-gem' }
|
75
|
+
post "/api/v1/users/#{user.id}/repos.json", params: { repo: { name: 'new-gem' } }
|
78
76
|
expect(response).to be_success
|
79
77
|
expect(JSON.parse(response.body)['user']).to eq JSON.parse(user.to_json)
|
80
78
|
}.to change { Repo.count } .by(1)
|
@@ -91,7 +89,7 @@ Feature: partials
|
|
91
89
|
Converting lurker to html
|
92
90
|
using lurker
|
93
91
|
|
94
|
-
|
95
|
-
|
92
|
+
public/lurker/index.html
|
93
|
+
public/lurker/api/v1/users/__user_id/repos-POST.html
|
96
94
|
"""
|
97
95
|
|
@@ -5,8 +5,6 @@ Feature: request nested schema scaffolding
|
|
5
5
|
Scenario: scaffold a json schema for a "repos/show" in a nested controller spec
|
6
6
|
Given a file named "spec/requests/repos_spec.rb" with:
|
7
7
|
"""ruby
|
8
|
-
require "spec_helper"
|
9
|
-
|
10
8
|
describe Api::V1::ReposController, :lurker do
|
11
9
|
let!(:user) do
|
12
10
|
User.where(name: 'razum2um').first_or_create!.tap do |u|
|
@@ -7,8 +7,6 @@ Feature: request schema scaffolding
|
|
7
7
|
Scenario: scaffold a json schema for a "users/index" in request spec
|
8
8
|
Given a file named "spec/requests/users_spec.rb" with:
|
9
9
|
"""ruby
|
10
|
-
require "spec_helper"
|
11
|
-
|
12
10
|
describe Api::V1::UsersController, :lurker do
|
13
11
|
let!(:user) do
|
14
12
|
User.where(name: 'razum2um', surname: 'Marley').first_or_create!
|
@@ -50,8 +50,6 @@ Feature: schema suffixes
|
|
50
50
|
"""
|
51
51
|
And a file named "spec/requests/updating_repos_spec.rb" with:
|
52
52
|
"""ruby
|
53
|
-
require "spec_helper"
|
54
|
-
|
55
53
|
describe Api::V1::ReposController, :lurker, type: :request do
|
56
54
|
|
57
55
|
let(:user) do
|
@@ -64,7 +62,7 @@ Feature: schema suffixes
|
|
64
62
|
|
65
63
|
it "updates a repo name" do
|
66
64
|
expect {
|
67
|
-
patch "/api/v1/users/#{user.name}/repos/#{repo.name}.json", repo: { name: 'updated-name' }
|
65
|
+
patch "/api/v1/users/#{user.name}/repos/#{repo.name}.json", params: { repo: { name: 'updated-name' } }
|
68
66
|
expect(response).to be_success
|
69
67
|
}.to change { repo.reload.name } .from('lurker').to('updated-name')
|
70
68
|
end
|
@@ -115,8 +113,6 @@ Feature: schema suffixes
|
|
115
113
|
"""
|
116
114
|
And a file named "spec/requests/failed_updating_repos_spec.rb" with:
|
117
115
|
"""ruby
|
118
|
-
require "spec_helper"
|
119
|
-
|
120
116
|
describe Api::V1::ReposController, type: :request do
|
121
117
|
|
122
118
|
let(:user) do
|
@@ -129,7 +125,7 @@ Feature: schema suffixes
|
|
129
125
|
|
130
126
|
it "fails to update a repo with a blank name", lurker: 'failed' do
|
131
127
|
expect {
|
132
|
-
patch "/api/v1/users/#{user.name}/repos/#{repo.name}.json", repo: { name: '' }
|
128
|
+
patch "/api/v1/users/#{user.name}/repos/#{repo.name}.json", params: { repo: { name: '' } }
|
133
129
|
expect(response).not_to be_success
|
134
130
|
}.not_to change { repo.reload.name }
|
135
131
|
end
|
@@ -62,8 +62,6 @@ Feature: schema updating within test suite
|
|
62
62
|
Scenario: json schema tests response parameters and request parameters and show errors from both using "users/update"
|
63
63
|
Given a file named "spec/controllers/api/v2/users_controller_blank_spec.rb" with:
|
64
64
|
"""ruby
|
65
|
-
require "spec_helper"
|
66
|
-
|
67
65
|
describe Api::V2::UsersController, :lurker do
|
68
66
|
render_views
|
69
67
|
|
@@ -72,7 +70,7 @@ Feature: schema updating within test suite
|
|
72
70
|
end
|
73
71
|
|
74
72
|
it "updates a user surname as string" do
|
75
|
-
patch :update, id: user.id, user: { name: '', surname: 'Marley' }
|
73
|
+
patch :update, params: { id: user.id, user: { name: '', surname: 'Marley' } }
|
76
74
|
expect(response).not_to be_success
|
77
75
|
end
|
78
76
|
end
|
@@ -93,8 +91,6 @@ Feature: schema updating within test suite
|
|
93
91
|
Scenario: json schema tests response parameters and update request parameters using "users/update"
|
94
92
|
Given a file named "spec/controllers/api/v2/users_controller_spec.rb" with:
|
95
93
|
"""ruby
|
96
|
-
require "spec_helper"
|
97
|
-
|
98
94
|
describe Api::V2::UsersController, :lurker do
|
99
95
|
render_views
|
100
96
|
|
@@ -103,7 +99,7 @@ Feature: schema updating within test suite
|
|
103
99
|
end
|
104
100
|
|
105
101
|
it "updates a user surname as string" do
|
106
|
-
patch :update, id: user.id, user: { surname: 'Marley' }
|
102
|
+
patch :update, params: { id: user.id, user: { surname: 'Marley' } }
|
107
103
|
expect(response).to be_success
|
108
104
|
end
|
109
105
|
end
|
@@ -2,17 +2,14 @@ Given /^a checked file "([^"]*)" with:$/ do |file_name, file_content|
|
|
2
2
|
write_file(file_name, file_content)
|
3
3
|
|
4
4
|
@files ||= {}
|
5
|
-
|
6
|
-
end
|
7
|
-
|
8
|
-
Given /^an empty directory named "([^"]*)"$/ do |dir_name|
|
9
|
-
in_current_dir { _rm_rf(dir_name) }
|
10
|
-
create_dir(dir_name)
|
5
|
+
in_current_directory { @files[md5(file_name)] = checksum(file_name) }
|
11
6
|
end
|
12
7
|
|
13
8
|
Given /^a service file with:$/ do |file_content|
|
14
|
-
|
15
|
-
|
9
|
+
in_current_directory do
|
10
|
+
rails_app_class = Rails.application.class
|
11
|
+
rails_app_name = rails_app_class.respond_to?(:module_parent_name) ? rails_app_class.module_parent_name : rails_app_class.parent_name
|
12
|
+
write_file("#{Lurker::DEFAULT_SERVICE_PATH}/#{rails_app_name}#{Lurker::Service::SUFFIX}", file_content)
|
16
13
|
end
|
17
14
|
end
|
18
15
|
|
@@ -83,7 +80,7 @@ end
|
|
83
80
|
Then /^the output should contain (failures|these lines):$/ do |_, lines|
|
84
81
|
out = all_output.dup
|
85
82
|
lines.split(/\n/).map(&:strip).each do |line|
|
86
|
-
next if line.blank?
|
83
|
+
next if line.strip!.blank?
|
87
84
|
expect(out).to match /#{Regexp.escape(line)}/
|
88
85
|
out.gsub!(/.*?#{Regexp.escape(line)}/m, '')
|
89
86
|
end
|
@@ -105,13 +102,13 @@ Then(/^I should see JSON response with "([^"]*)"$/) do |name|
|
|
105
102
|
end
|
106
103
|
|
107
104
|
Then /(?:a|the) checked file "([^"]*)" should not change$/ do |file_name|
|
108
|
-
|
105
|
+
in_current_directory do
|
109
106
|
expect(@files.try(:[], md5(file_name))).to eq checksum(file_name)
|
110
107
|
end
|
111
108
|
end
|
112
109
|
|
113
110
|
Then /(?:a|the) checked file "([^"]*)" should change$/ do |file_name|
|
114
|
-
|
111
|
+
in_current_directory do
|
115
112
|
expect(@files.try(:[], md5(file_name))).not_to eq checksum(file_name)
|
116
113
|
end
|
117
114
|
end
|
data/features/support/env.rb
CHANGED
@@ -6,11 +6,19 @@ SimpleCov.start do
|
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
+
def relative_example_path
|
10
|
+
if rails_version = ENV['BUNDLE_GEMFILE'].to_s.match(/rails_\d+/)
|
11
|
+
"tmp/lurker_app_#{rails_version}"
|
12
|
+
else
|
13
|
+
raise "Export BUNDLE_GEMFILE=gemfiles/rails... explicitly"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
9
17
|
def example_path
|
10
|
-
if rails_version = ENV['BUNDLE_GEMFILE'].to_s.match(/rails_\d
|
18
|
+
if rails_version = ENV['BUNDLE_GEMFILE'].to_s.match(/rails_\d+/)
|
11
19
|
File.expand_path("../../../tmp/lurker_app_#{rails_version}", __FILE__)
|
12
20
|
else
|
13
|
-
raise "
|
21
|
+
raise "Export BUNDLE_GEMFILE=gemfiles/rails... explicitly"
|
14
22
|
end
|
15
23
|
end
|
16
24
|
|
@@ -23,21 +31,53 @@ World(RSpec::Matchers)
|
|
23
31
|
require 'capybara'
|
24
32
|
require 'capybara/dsl'
|
25
33
|
require 'capybara/cucumber'
|
26
|
-
require '
|
34
|
+
require 'webdrivers/chromedriver'
|
27
35
|
require "#{example_path}/config/environment"
|
28
36
|
require 'database_cleaner'
|
29
37
|
require 'database_cleaner/cucumber'
|
30
38
|
|
31
|
-
Capybara.
|
32
|
-
Capybara.
|
39
|
+
Capybara.register_driver :chrome do |app|
|
40
|
+
Capybara::Selenium::Driver.new(app, browser: :chrome)
|
41
|
+
end
|
33
42
|
|
43
|
+
Capybara.register_driver :headless_chrome do |app|
|
44
|
+
Selenium::WebDriver.logger.level = :debug if ENV['CAPYBARA_DEBUG'].present?
|
45
|
+
browser_capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs: { browser: 'ALL' })
|
46
|
+
browser_options = Selenium::WebDriver::Chrome::Options.new(args: %w[headless disable-gpu no-sandbox disable-dev-shm-usage window-size=1900,1080])
|
47
|
+
browser_options.add_argument('--ignore-certificate-errors')
|
48
|
+
# Disable w3c mode (default as of Chrome 75) to allow for logging
|
49
|
+
browser_options.add_option(:w3c, false)
|
50
|
+
Capybara::Selenium::Driver.new app,
|
51
|
+
browser: :chrome,
|
52
|
+
options: browser_options,
|
53
|
+
desired_capabilities: browser_capabilities
|
54
|
+
end
|
55
|
+
|
56
|
+
Capybara.app = Rails.application
|
57
|
+
Capybara.server = :puma, { Silent: true, Threads: '1:1' }
|
58
|
+
Capybara.javascript_driver = ENV['CAPYBARA_JS_DRIVER']&.to_sym || :headless_chrome
|
34
59
|
DatabaseCleaner.strategy = :truncation
|
35
60
|
|
61
|
+
# otherwise it cleans up all rails folder
|
62
|
+
# https://github.com/cucumber/aruba/blob/bf612766ac51e28ca354e735980cd8a5d7eb296f/lib/aruba/setup.rb#L27L31
|
63
|
+
# it force deletes the working_directory,
|
64
|
+
# but it has to be working_directory to cd in and run `bin/rspec`
|
65
|
+
# this forces @no-clobber everywhere
|
66
|
+
# use CLEAN=1 env var to clean proper places
|
67
|
+
module ArubaSetupNoClobber
|
68
|
+
def working_directory(clobber = true)
|
69
|
+
super(false)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
Aruba::Setup.prepend(ArubaSetupNoClobber)
|
73
|
+
|
36
74
|
# see: https://github.com/colszowka/simplecov/issues/234
|
37
75
|
Aruba.configure do |config|
|
38
|
-
config.
|
39
|
-
|
40
|
-
|
76
|
+
config.working_directory = relative_example_path # Aruba::Contracts::RelativePath
|
77
|
+
config.activate_announcer_on_command_failure = [:stdout]
|
78
|
+
config.before :command do |cmd|
|
79
|
+
set_environment_variable 'SIMPLECOV_CMDNAME', Digest::MD5.hexdigest(cmd.object_id.to_s)
|
80
|
+
set_environment_variable 'SIMPLECOV_ROOT', File.expand_path('../../..', __FILE__)
|
41
81
|
end
|
42
82
|
end
|
43
83
|
|
@@ -47,8 +87,8 @@ Before do
|
|
47
87
|
DatabaseCleaner.start
|
48
88
|
if ENV['CLEAN']
|
49
89
|
system "bin/spring stop"
|
50
|
-
%w[lurker
|
51
|
-
|
90
|
+
%w[lurker public/lurker spec/requests spec/controllers].each do |dir_name|
|
91
|
+
in_current_directory { remove(dir_name, force: true) }
|
52
92
|
end
|
53
93
|
end
|
54
94
|
end
|
@@ -53,8 +53,6 @@ Feature: test endpoint
|
|
53
53
|
Scenario: json schema tests request and response using "users/update"
|
54
54
|
Given a file named "spec/controllers/api/v1/users_controller_spec.rb" with:
|
55
55
|
"""ruby
|
56
|
-
require "spec_helper"
|
57
|
-
|
58
56
|
describe Api::V1::UsersController, :lurker do
|
59
57
|
render_views
|
60
58
|
|
@@ -63,7 +61,7 @@ Feature: test endpoint
|
|
63
61
|
end
|
64
62
|
|
65
63
|
it "updates a user" do
|
66
|
-
patch :update, id: user.id, user: { name: 'Bob' }
|
64
|
+
patch :update, params: { id: user.id, user: { name: 'Bob' } }
|
67
65
|
expect(response).to be_success
|
68
66
|
end
|
69
67
|
end
|
@@ -75,8 +73,6 @@ Feature: test endpoint
|
|
75
73
|
Scenario: json schema tests response parameters and tell what fails using "users/update"
|
76
74
|
Given a file named "spec/controllers/api/v1/users_controller_blank_spec.rb" with:
|
77
75
|
"""ruby
|
78
|
-
require "spec_helper"
|
79
|
-
|
80
76
|
describe Api::V1::UsersController, :lurker do
|
81
77
|
render_views
|
82
78
|
|
@@ -85,7 +81,7 @@ Feature: test endpoint
|
|
85
81
|
end
|
86
82
|
|
87
83
|
it "updates a user" do
|
88
|
-
patch :update, id: user.id, user: { name: '' }, format: 'json'
|
84
|
+
patch :update, params: { id: user.id, user: { name: '' }, format: 'json' }
|
89
85
|
expect(response).not_to be_success
|
90
86
|
end
|
91
87
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gem "rails", "~> 4.2"
|
4
|
+
gem "bigdecimal", "~> 1.4"
|
5
|
+
gem "pg", "<= 0.20" # doesnt use 1.0 by install, 0.21 too many warnings
|
6
|
+
|
7
|
+
gem "rails-forward_compatible_controller_tests", "> 0"
|
8
|
+
|
9
|
+
gem "jquery-rails"
|
10
|
+
gem "bootstrap-sass"
|
11
|
+
gem "remotipart"
|
12
|
+
gem "uglifier"
|
13
|
+
|
14
|
+
gemspec :path => "../"
|
data/lib/lurker.rb
CHANGED
data/lib/lurker/cli.rb
CHANGED
@@ -18,7 +18,7 @@ module Lurker
|
|
18
18
|
attr_accessor :content
|
19
19
|
|
20
20
|
def self.templates_root
|
21
|
-
|
21
|
+
Lurker::BUNDLED_TEMPLATES_PATH
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.assets_root
|
@@ -106,7 +106,10 @@ module Lurker
|
|
106
106
|
|
107
107
|
def setup_rendering_engine!
|
108
108
|
I18n.config.enforce_available_locales = true
|
109
|
-
Lurker::RenderingController.prepend_view_path templates_root
|
109
|
+
Lurker::RenderingController.prepend_view_path Lurker::Cli.templates_root
|
110
|
+
if options[:templates].present?
|
111
|
+
Lurker::RenderingController.prepend_view_path Pathname.new(options[:templates]).expand_path
|
112
|
+
end
|
110
113
|
Lurker::RenderingController.config.assets_dir = assets_root
|
111
114
|
end
|
112
115
|
|
@@ -159,7 +162,6 @@ module Lurker
|
|
159
162
|
@html_options ||= {
|
160
163
|
static_html: true,
|
161
164
|
url_base_path: url_base_path.prepend('/'),
|
162
|
-
template_directory: templates_root,
|
163
165
|
assets_directory: assets_root,
|
164
166
|
assets: assets,
|
165
167
|
html_directory: output_path,
|
@@ -197,10 +199,6 @@ module Lurker
|
|
197
199
|
Lurker::Cli.assets_root
|
198
200
|
end
|
199
201
|
|
200
|
-
def templates_root
|
201
|
-
Lurker::Cli.templates_root
|
202
|
-
end
|
203
|
-
|
204
202
|
def asset_logical_path(path)
|
205
203
|
path = Pathname.new(path) unless path.is_a? Pathname
|
206
204
|
path.sub %r{-[0-9a-f]{40}\.}, '.'
|
data/lib/lurker/endpoint.rb
CHANGED
@@ -192,15 +192,15 @@ module Lurker
|
|
192
192
|
def word_wrap(text)
|
193
193
|
# strip .json# | .json.yml# | .json.yml.erb#
|
194
194
|
text = text.reverse
|
195
|
-
text.gsub!(/(\n|^)#bre\./, "\nbre.")
|
196
|
-
text.gsub!(/(\n|^)#lmy\./, "\nlmy.")
|
197
|
-
text.gsub!(/(\n|^)#nosj\./, "\nnosj.")
|
195
|
+
text.gsub!(/(\n|^)#bre\./, "\nbre.") # erb
|
196
|
+
text.gsub!(/(\n|^)#lmy\./, "\nlmy.") # yml
|
197
|
+
text.gsub!(/(\n|^)#nosj\./, "\nnosj.") # json
|
198
198
|
text.strip!
|
199
199
|
text = text.reverse
|
200
200
|
|
201
201
|
text.gsub!(/\s+in schema/m, "\n in schema")
|
202
202
|
if defined?(Rails)
|
203
|
-
text.gsub!(
|
203
|
+
text.gsub!(Regexp.new("#{Rails.root}\/"), "")
|
204
204
|
end
|
205
205
|
text
|
206
206
|
end
|
@@ -9,7 +9,11 @@ module Lurker
|
|
9
9
|
|
10
10
|
def to_validation_schema
|
11
11
|
set_additional_properties_false_on(to_hash).tap do |schema|
|
12
|
-
|
12
|
+
if uri.class == URI::Generic
|
13
|
+
schema[Json::ID] = uri.path
|
14
|
+
else
|
15
|
+
schema[Json::ID] = uri.to_s
|
16
|
+
end
|
13
17
|
end
|
14
18
|
end
|
15
19
|
|
data/lib/lurker/json/parser.rb
CHANGED
@@ -16,7 +16,7 @@ module Lurker
|
|
16
16
|
@parent_schema = options[:parent_schema]
|
17
17
|
@parent_property = options[:parent_property]
|
18
18
|
@polymorph_if_empty = options.fetch(:polymorph_if_empty, false)
|
19
|
-
@uri = options[:uri] || @parent_schema
|
19
|
+
@uri = options[:uri] || @parent_schema&.uri
|
20
20
|
@strategy = nil
|
21
21
|
end
|
22
22
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/inflector'
|
2
|
+
require 'active_support/hash_with_indifferent_access'
|
2
3
|
|
3
4
|
# An BasePresenter for Lurker::Service
|
4
5
|
class Lurker::ServicePresenter < Lurker::BasePresenter
|
@@ -62,7 +63,7 @@ class Lurker::ServicePresenter < Lurker::BasePresenter
|
|
62
63
|
end
|
63
64
|
|
64
65
|
def url_name
|
65
|
-
@url_name ||=
|
66
|
+
@url_name ||= name.gsub(/[^a-z0-9\-_]+/i, '_')
|
66
67
|
end
|
67
68
|
|
68
69
|
def url(extension = ".html")
|