title_estuary 1.0.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/MIT-LICENSE +20 -0
- data/README.rdoc +104 -0
- data/Rakefile +9 -0
- data/VERSION +1 -0
- data/lib/title_estuary/inherited_resources_support.rb +29 -0
- data/lib/title_estuary.rb +114 -0
- data/tasks/doc.task +28 -0
- data/tasks/gem.task +39 -0
- data/tasks/test.task +23 -0
- data/test/default_titles_test.rb +110 -0
- data/test/dynamic_page_title_test.rb +48 -0
- data/test/inherited_resources_integration_test.rb +107 -0
- data/test/interpolated_page_titles_test.rb +58 -0
- data/test/rails_integration_test.rb +29 -0
- data/test/shoulda_macros/page_title_macros.rb +32 -0
- data/test/simple_custom_titles_test.rb +34 -0
- data/test/test_helper.rb +26 -0
- data/test/village_model_and_controller.rb +22 -0
- metadata +76 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 James Rosen
|
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,104 @@
|
|
1
|
+
Title Estuary is a gem/plugin that makes it easy to set page titles.
|
2
|
+
It it built with internationalization in mind. It requires
|
3
|
+
ActiveSupport's I18N, but should be usable with frameworks other
|
4
|
+
than Rails.
|
5
|
+
|
6
|
+
=== How-To
|
7
|
+
|
8
|
+
==== 1: tell Rails about the gem:
|
9
|
+
|
10
|
+
# in RAILS_ROOT/config/environment.rb:
|
11
|
+
config.gem 'title_estuary', :source => 'http://gemcutter.org'
|
12
|
+
|
13
|
+
==== 2: have Rails install the gem:
|
14
|
+
|
15
|
+
[sudo] rake gems:install
|
16
|
+
|
17
|
+
==== 3: set up your layout:
|
18
|
+
|
19
|
+
# in RAILS_ROOT/app/views/layouts/application.html.erb:
|
20
|
+
<html ...>
|
21
|
+
<head ...>
|
22
|
+
<title><%= page_title %></title>
|
23
|
+
...
|
24
|
+
</head>
|
25
|
+
<body>
|
26
|
+
<h1><%= page_title %></h1>
|
27
|
+
...
|
28
|
+
</body>
|
29
|
+
</html>
|
30
|
+
|
31
|
+
==== 4. customize your titles:
|
32
|
+
|
33
|
+
Use the format "page.title.controller_name.action_name"
|
34
|
+
|
35
|
+
# in RAILS_ROOT/config/locales/en.yml:
|
36
|
+
en:
|
37
|
+
page:
|
38
|
+
title:
|
39
|
+
accounts:
|
40
|
+
new: "Sign Up"
|
41
|
+
sessions:
|
42
|
+
new: "Sign In"
|
43
|
+
projects:
|
44
|
+
index: "Your projects"
|
45
|
+
new: "Start a new project"
|
46
|
+
|
47
|
+
If you want to use any interpolated strings, make sure
|
48
|
+
you define an <tt>#interpolation_options</tt> method in
|
49
|
+
your controller:
|
50
|
+
|
51
|
+
# in RAILS_ROOT/config/locales/en.yml:
|
52
|
+
en:
|
53
|
+
page:
|
54
|
+
title:
|
55
|
+
projects:
|
56
|
+
index: "All {{number_of_projects}} of your projects"
|
57
|
+
show: "Project {{project_name}}"
|
58
|
+
edit: "Edit project {{project_name}}"
|
59
|
+
|
60
|
+
# An example controller (that would be defined
|
61
|
+
# in RAILS_ROOT/app/controllers/projects_controller.rb).
|
62
|
+
class ProjectsController < ActionController::Base
|
63
|
+
# An example definition of <tt>#interpolation_options</tt>
|
64
|
+
# that sets certain project-related values as applicable.
|
65
|
+
#
|
66
|
+
# @return [Hash] a hash of interpolation values
|
67
|
+
def interpolation_options
|
68
|
+
returning({}) do |result|
|
69
|
+
result[:number_of_projects] = @projects.size if @projects.present?
|
70
|
+
result[:project_name] = @project.name if @project.present?
|
71
|
+
result[:project_id] = params[:id]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
hide_action :interpolation_options
|
75
|
+
end
|
76
|
+
|
77
|
+
If you need more dynamic titles than simple interpolation affords,
|
78
|
+
set the title manually in an action:
|
79
|
+
|
80
|
+
# in RAILS_ROOT/app/controllers/projects_controller.rb:
|
81
|
+
class ProjectsController < ActionController::Base
|
82
|
+
def show
|
83
|
+
@project = Project.find(params[:id])
|
84
|
+
self.page_title = "A title based on #{@project.some_complex_string}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
or in a filter:
|
89
|
+
|
90
|
+
# in RAILS_ROOT/app/controllers/projects_controller.rb:
|
91
|
+
class ProjectsController < ActionController::Base
|
92
|
+
before_filter :set_title
|
93
|
+
private
|
94
|
+
def set_title
|
95
|
+
self.page_title = "Some complex title"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
or from a view:
|
100
|
+
|
101
|
+
# in RAILS_ROOT/app/view/projects/index.html.erb:
|
102
|
+
<% content_for :page_title do %>
|
103
|
+
Some complex page title
|
104
|
+
<% end %>
|
data/Rakefile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
desc "Default: run all tests, including features"
|
2
|
+
task :default => [ 'test' ]
|
3
|
+
|
4
|
+
TITLE_ESTUARY_PROJECT_ROOT = File.expand_path(File.dirname(__FILE__))
|
5
|
+
LOAD_TITLE_ESTUARY_BUILD_TASKS = true
|
6
|
+
|
7
|
+
Dir.glob('tasks/*.task').each do |taskfile|
|
8
|
+
load File.expand_path("./#{taskfile}")
|
9
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module TitleEstuary
|
2
|
+
|
3
|
+
module InheritedResourcesSupport
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
# @return [#to_s] the requested_resource as loaded by
|
8
|
+
# InheritedResources.
|
9
|
+
def page_title_resource
|
10
|
+
# it should be loaded by now, but if not, don't
|
11
|
+
# make a special request on our behalf:
|
12
|
+
get_resource_ivar
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [String] an improved guess for the name of the requested resource.
|
16
|
+
def page_title_singular_resource_name
|
17
|
+
resource_name = if resource_class
|
18
|
+
if resource_class.respond_to?(:human_name)
|
19
|
+
resource_class.human_name
|
20
|
+
else
|
21
|
+
resource_class.name.humanize
|
22
|
+
end
|
23
|
+
else
|
24
|
+
params[:controller].to_s.singularize
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# @author James Rosen
|
2
|
+
module TitleEstuary
|
3
|
+
|
4
|
+
# When TitleEstuary is included by a controller,
|
5
|
+
# this hook prevents ActionPack from using
|
6
|
+
# <tt>#page_title</tt> as an action and makes that
|
7
|
+
# method available to helpers and views; it also
|
8
|
+
# auto-includes TitleEstuary::InheritedResourcesSupport
|
9
|
+
# if applicable.
|
10
|
+
def self.included(base)
|
11
|
+
base.send :include, TitleEstuary::InstanceMethods
|
12
|
+
base.hide_action(:page_title) if base.respond_to?(:hide_action)
|
13
|
+
base.helper_method(:page_title, :page_title=) if base.respond_to?(:helper_method)
|
14
|
+
if Object.const_defined?(:InheritedResources) && base < ::InheritedResources::Base
|
15
|
+
base.send :include, TitleEstuary::InheritedResourcesSupport
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
|
21
|
+
# Get the page title. First checks for a dynamically-set
|
22
|
+
# title (set via <tt>#page_title=</tt> or via
|
23
|
+
# <tt>content_for :page_title</tt>); if none has been set,
|
24
|
+
# uses a version from I18n under the key
|
25
|
+
# 'page.title.<controller>.<action>'; if no such value exists,
|
26
|
+
# tries to generate a reasonable sane default.
|
27
|
+
#
|
28
|
+
# @return [String] the page title
|
29
|
+
def page_title
|
30
|
+
return @content_for_page_title if @content_for_page_title.present?
|
31
|
+
self.page_title = look_up_or_generate_page_title
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
# Sets the page title.
|
37
|
+
#
|
38
|
+
# Available to views both as a helper method:
|
39
|
+
#
|
40
|
+
# <% self.page_title = '...' -%>
|
41
|
+
#
|
42
|
+
# and via <tt>:content_for :page_title</tt>:
|
43
|
+
#
|
44
|
+
# <% content_for :page_title do %>
|
45
|
+
# ...
|
46
|
+
# <% end %>
|
47
|
+
def page_title=(title)
|
48
|
+
@content_for_page_title = title
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# @return [String] the I18n version of the page
|
54
|
+
# title, defaulting to the generated version.
|
55
|
+
#
|
56
|
+
# @see #page_title_i18n_key
|
57
|
+
# @see #default_page_title_from_controller_and_action
|
58
|
+
def look_up_or_generate_page_title
|
59
|
+
given_options = if self.respond_to?(:interpolation_options)
|
60
|
+
interpolation_options
|
61
|
+
else
|
62
|
+
{}
|
63
|
+
end
|
64
|
+
default = default_page_title_from_controller_and_action
|
65
|
+
options = given_options.merge(:default => default)
|
66
|
+
I18n.t page_title_i18n_key, options
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Symbol] the I18n key for the page title for
|
70
|
+
# this controller/action pair.
|
71
|
+
def page_title_i18n_key
|
72
|
+
"page.title.#{params[:controller]}.#{params[:action]}".to_sym
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [String] a reasonably sane default title for
|
76
|
+
# this controller/action pair.
|
77
|
+
def default_page_title_from_controller_and_action
|
78
|
+
action = params[:action].to_s
|
79
|
+
resource_name = page_title_singular_resource_name
|
80
|
+
resource = page_title_resource
|
81
|
+
case action
|
82
|
+
when 'index'
|
83
|
+
"All #{resource_name.pluralize.titleize}"
|
84
|
+
when 'new', 'create'
|
85
|
+
"New #{resource_name.singularize.titleize}"
|
86
|
+
when 'show'
|
87
|
+
"#{resource_name.singularize.titleize} #{resource}"
|
88
|
+
when 'edit', 'update'
|
89
|
+
"Edit #{resource_name.singularize.titleize} #{resource}"
|
90
|
+
else
|
91
|
+
if resource.present?
|
92
|
+
"#{action.titleize} #{resource_name.singularize.titleize} #{resource}"
|
93
|
+
else
|
94
|
+
"#{action.titleize} #{resource_name.pluralize.titleize}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# @return [#to_s] an instance variable representing the requested
|
100
|
+
# resource if it's in an obvious location.
|
101
|
+
def page_title_resource
|
102
|
+
if params[:id]
|
103
|
+
instance_variable_get(:"@#{page_title_singular_resource_name}") || params[:id]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# @return [String] a guess for the name of the requested resource.
|
108
|
+
def page_title_singular_resource_name
|
109
|
+
params[:controller].singularize
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
data/tasks/doc.task
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# don't load these tasks if this project is used as a Rails plugin:
|
2
|
+
if Object.const_defined?(:LOAD_TITLE_ESTUARY_BUILD_TASKS) && LOAD_TITLE_ESTUARY_BUILD_TASKS
|
3
|
+
require 'yard'
|
4
|
+
require 'yard/rake/yardoc_task'
|
5
|
+
|
6
|
+
desc "Generate RDoc"
|
7
|
+
task :doc => ['doc:generate']
|
8
|
+
|
9
|
+
namespace :doc do
|
10
|
+
|
11
|
+
doc_dir = "#{TITLE_ESTUARY_PROJECT_ROOT}/doc/rdoc"
|
12
|
+
readme = "#{TITLE_ESTUARY_PROJECT_ROOT}/README.rdoc"
|
13
|
+
|
14
|
+
YARD::Rake::YardocTask.new(:generate) do |yt|
|
15
|
+
yt.files = FileList[
|
16
|
+
"#{TITLE_ESTUARY_PROJECT_ROOT}/lib/**/*.rb",
|
17
|
+
"#{TITLE_ESTUARY_PROJECT_ROOT}/README.rdoc"
|
18
|
+
]
|
19
|
+
yt.options = ['--output-dir', doc_dir, '--readme', readme]
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Remove generated documenation"
|
23
|
+
task :clean do
|
24
|
+
rm_r doc_dir if File.exists?(doc_dir)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
data/tasks/gem.task
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# don't load these tasks if this project is used as a Rails plugin:
|
2
|
+
if Object.const_defined?(:LOAD_TITLE_ESTUARY_BUILD_TASKS) && LOAD_TITLE_ESTUARY_BUILD_TASKS
|
3
|
+
|
4
|
+
gem_files = FileList[
|
5
|
+
"[A-Z]*",
|
6
|
+
"{lib,tasks}/**/*"
|
7
|
+
]
|
8
|
+
|
9
|
+
#raise gem_files.to_a.inspect
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |s|
|
14
|
+
s.name = "title_estuary"
|
15
|
+
s.summary = 'Easy, internationalized page titles'
|
16
|
+
s.email = 'james.a.rosen@gmail.com'
|
17
|
+
s.homepage = "http://github.com/gcnovus/title_estuary"
|
18
|
+
s.description = 'Title Estuary speeds up development by giving you good default titles and simple customizability, including internationalization.'
|
19
|
+
s.authors = ['James Rosen']
|
20
|
+
s.files = gem_files
|
21
|
+
s.require_paths = ['lib']
|
22
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Title Estuary: RDoc", "--charset", "utf-8"]
|
23
|
+
end
|
24
|
+
rescue LoadError
|
25
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
|
26
|
+
end
|
27
|
+
|
28
|
+
namespace :pkg do
|
29
|
+
|
30
|
+
pkg_dir = File.join(TITLE_ESTUARY_PROJECT_ROOT, 'pkg')
|
31
|
+
|
32
|
+
desc "Remove the pkg/ directory and all built gems"
|
33
|
+
task :clean do
|
34
|
+
rm_r pkg_dir if File.exists?(pkg_dir)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/tasks/test.task
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# don't load these tasks if this project is used as a Rails plugin:
|
2
|
+
if Object.const_defined?(:LOAD_TITLE_ESTUARY_BUILD_TASKS) && LOAD_TITLE_ESTUARY_BUILD_TASKS
|
3
|
+
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
LIB_DIRECTORIES = FileList.new do |fl|
|
7
|
+
fl.include "#{TITLE_ESTUARY_PROJECT_ROOT}/lib"
|
8
|
+
fl.include "#{TITLE_ESTUARY_PROJECT_ROOT}/test/lib"
|
9
|
+
end
|
10
|
+
|
11
|
+
TEST_FILES = FileList.new do |fl|
|
12
|
+
fl.include "#{TITLE_ESTUARY_PROJECT_ROOT}/test/**/*_test.rb"
|
13
|
+
fl.exclude "#{TITLE_ESTUARY_PROJECT_ROOT}/test/test_helper.rb"
|
14
|
+
fl.exclude "#{TITLE_ESTUARY_PROJECT_ROOT}/test/lib/**/*.rb"
|
15
|
+
end
|
16
|
+
|
17
|
+
Rake::TestTask.new(:test) do |t|
|
18
|
+
t.libs = LIB_DIRECTORIES
|
19
|
+
t.test_files = TEST_FILES
|
20
|
+
t.verbose = true
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/village_model_and_controller'
|
3
|
+
|
4
|
+
class DefaultTitlesTest < ActionController::TestCase
|
5
|
+
include PageTitleMacros
|
6
|
+
tests VillagesController
|
7
|
+
|
8
|
+
context 'a RESTful, titleize controller' do
|
9
|
+
|
10
|
+
context 'with no custom page titles set up' do
|
11
|
+
|
12
|
+
setup { clear_translations! }
|
13
|
+
|
14
|
+
context 'on a GET to :index' do
|
15
|
+
setup { get :index }
|
16
|
+
should_set_the_page_title_to 'All Villages'
|
17
|
+
should 'not generate the title twice' do
|
18
|
+
@controller.page_title
|
19
|
+
@controller.stubs :look_up_or_generate_page_title
|
20
|
+
@controller.page_title
|
21
|
+
assert_received @controller, :look_up_or_generate_page_title do |expect|
|
22
|
+
expect.never
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'on a GET to :new' do
|
28
|
+
setup { get :new }
|
29
|
+
should_set_the_page_title_to 'New Village'
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'on a POST to :create that fails' do
|
33
|
+
setup { post :create }
|
34
|
+
should_set_the_page_title_to 'New Village'
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'on a GET to :show for a resource that exists' do
|
38
|
+
setup do
|
39
|
+
Village.stubs(:find).returns(Village.new('Bostonburgh'))
|
40
|
+
get :show, :id => 'anything'
|
41
|
+
end
|
42
|
+
should_set_the_page_title_to "Village Bostonburgh"
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'on a GET to :show for a resource that does not exist (or is not set to an obvious instance variable)' do
|
46
|
+
setup do
|
47
|
+
Village.stubs(:find).returns(nil)
|
48
|
+
get :show, :id => '2'
|
49
|
+
end
|
50
|
+
should_set_the_page_title_to "Village 2"
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'on a GET to :edit for a resource that exists' do
|
54
|
+
setup do
|
55
|
+
Village.stubs(:find).returns(Village.new('Gloucestershire'))
|
56
|
+
get :edit, :id => 'something'
|
57
|
+
end
|
58
|
+
should_set_the_page_title_to "Edit Village Gloucestershire"
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'on a GET to :edit for a resource that does not exist (or is not set to an obvious instance variable)' do
|
62
|
+
setup do
|
63
|
+
Village.stubs(:find).returns(nil)
|
64
|
+
get :edit, :id => '3'
|
65
|
+
end
|
66
|
+
should_set_the_page_title_to "Edit Village 3"
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'on a PUT to :update for a resource that exists' do
|
70
|
+
setup do
|
71
|
+
Village.stubs(:find).returns(Village.new('East Umbridge'))
|
72
|
+
put :update, :id => 'seven'
|
73
|
+
end
|
74
|
+
should_set_the_page_title_to "Edit Village East Umbridge"
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'on a PUT to :update for a resource that does not exist (or is not set to an obvious instance variable)' do
|
78
|
+
setup do
|
79
|
+
Village.stubs(:find).returns(nil)
|
80
|
+
put :update, :id => '100'
|
81
|
+
end
|
82
|
+
should_set_the_page_title_to "Edit Village 100"
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'on a GET to a custom collection action' do
|
86
|
+
setup { get :burninated }
|
87
|
+
should_set_the_page_title_to "Burninated Villages"
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'on a GET on a custom member action for a resource that exists' do
|
91
|
+
setup do
|
92
|
+
Village.stubs(:find).returns(Village.new('Parrotshire'))
|
93
|
+
get :burninate, :id => '14'
|
94
|
+
end
|
95
|
+
should_set_the_page_title_to "Burninate Village Parrotshire"
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'on a GET to a custom member action for a resource that does not exist (or is not set to an obvious instance variable)' do
|
99
|
+
setup do
|
100
|
+
Village.stubs(:find).returns(nil)
|
101
|
+
get :burninate, :id => '9'
|
102
|
+
end
|
103
|
+
should_set_the_page_title_to "Burninate Village 9"
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/village_model_and_controller'
|
3
|
+
|
4
|
+
VillagesController.class_eval do
|
5
|
+
def index_with_dynamic_title
|
6
|
+
self.page_title = 'A Custom Title'
|
7
|
+
index_without_dynamic_title
|
8
|
+
end
|
9
|
+
alias_method :index_without_dynamic_title, :index
|
10
|
+
end
|
11
|
+
|
12
|
+
class DynamicPageTitle < ActionController::TestCase
|
13
|
+
include PageTitleMacros
|
14
|
+
tests VillagesController
|
15
|
+
|
16
|
+
context 'a RESTful, titleize controller' do
|
17
|
+
|
18
|
+
context 'that sets a page title dynamically' do
|
19
|
+
|
20
|
+
setup do
|
21
|
+
clear_translations!
|
22
|
+
VillagesController.class_eval do
|
23
|
+
alias_method :index, :index_with_dynamic_title
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
teardown do
|
28
|
+
VillagesController.class_eval do
|
29
|
+
alias_method :index, :index_without_dynamic_title
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
should 'use the dynamic title instead of the default' do
|
34
|
+
get :index
|
35
|
+
assert_page_title_is 'A Custom Title'
|
36
|
+
end
|
37
|
+
|
38
|
+
should 'use the dynamic title instead of a custom one from the I18n framework' do
|
39
|
+
define_translation 'page.title.villages.index', 'something else'
|
40
|
+
get :index
|
41
|
+
assert_page_title_is 'A Custom Title'
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require 'inherited_resources'
|
3
|
+
require 'inherited_resources/actions'
|
4
|
+
require 'inherited_resources/base_helpers'
|
5
|
+
require 'inherited_resources/class_methods'
|
6
|
+
require 'inherited_resources/url_helpers'
|
7
|
+
require 'inherited_resources/base'
|
8
|
+
|
9
|
+
class Pizza
|
10
|
+
def initialize(name); @name = name.to_s; end
|
11
|
+
def to_s; @name; end
|
12
|
+
def to_param; '1'; end
|
13
|
+
def method_missing(*args, &block); self; end
|
14
|
+
end
|
15
|
+
|
16
|
+
class DeliciousThingsController < InheritedResources::Base
|
17
|
+
self.resource_class = Pizza
|
18
|
+
include TitleEstuary
|
19
|
+
def cheesey; index; end
|
20
|
+
def add_topping; show; end
|
21
|
+
def pizza_url(*args); delicious_thing_url(*args); end
|
22
|
+
end
|
23
|
+
|
24
|
+
ActionController::Routing::Routes.draw do |map|
|
25
|
+
map.resources :delicious_things, :collection => { :cheesey => :get },
|
26
|
+
:member => { :add_topping => :get }
|
27
|
+
end
|
28
|
+
|
29
|
+
class InheritedResourcesIntegrationTest < ActionController::TestCase
|
30
|
+
include PageTitleMacros
|
31
|
+
tests DeliciousThingsController
|
32
|
+
|
33
|
+
context 'a RESTful controller using both Title Estuary and Inherited Resources' do
|
34
|
+
|
35
|
+
context 'with custom page titles that involve interpolation' do
|
36
|
+
|
37
|
+
setup do
|
38
|
+
clear_translations!
|
39
|
+
end
|
40
|
+
|
41
|
+
should 'have inherited-resources support installed' do
|
42
|
+
assert DeliciousThingsController < TitleEstuary::InheritedResourcesSupport
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'on a GET to :index' do
|
46
|
+
setup do
|
47
|
+
Pizza.stubs(:find).returns([])
|
48
|
+
get :index
|
49
|
+
end
|
50
|
+
should_set_the_page_title_to 'All Pizzas'
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'on a GET to :new' do
|
54
|
+
setup { get :new }
|
55
|
+
should_set_the_page_title_to 'New Pizza'
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'on a POST to :create that fails' do
|
59
|
+
setup { post :create }
|
60
|
+
should_set_the_page_title_to 'New Pizza'
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'on a GET to :show' do
|
64
|
+
setup do
|
65
|
+
Pizza.stubs(:find).returns(Pizza.new('Vegetarian Special'))
|
66
|
+
get :show, :id => 'anything'
|
67
|
+
end
|
68
|
+
should_set_the_page_title_to "Pizza Vegetarian Special"
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'on a GET to :edit' do
|
72
|
+
setup do
|
73
|
+
Pizza.stubs(:find).returns(Pizza.new('NY Thin Crust'))
|
74
|
+
get :edit, :id => 'something'
|
75
|
+
end
|
76
|
+
should_set_the_page_title_to "Edit Pizza NY Thin Crust"
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'on a PUT to :update' do
|
80
|
+
setup do
|
81
|
+
Pizza.stubs(:find).returns(Pizza.new('Neapolitan'))
|
82
|
+
put :update, :id => 'seven'
|
83
|
+
end
|
84
|
+
should_set_the_page_title_to "Edit Pizza Neapolitan"
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'on a GET to a custom collection action' do
|
88
|
+
setup do
|
89
|
+
Pizza.stubs(:find).returns([])
|
90
|
+
get :cheesey
|
91
|
+
end
|
92
|
+
should_set_the_page_title_to "Cheesey Pizzas"
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'on a GET on a custom member action for a resource that exists' do
|
96
|
+
setup do
|
97
|
+
Pizza.stubs(:find).returns(Pizza.new('Margherita'))
|
98
|
+
get :add_topping, :id => '14'
|
99
|
+
end
|
100
|
+
should_set_the_page_title_to "Add Topping Pizza Margherita"
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/village_model_and_controller'
|
3
|
+
|
4
|
+
class InterpolatedPageTitlesTest < ActionController::TestCase
|
5
|
+
include PageTitleMacros
|
6
|
+
tests VillagesController
|
7
|
+
|
8
|
+
context 'a RESTful, titleize controller' do
|
9
|
+
|
10
|
+
context 'with custom page titles that involve interpolation' do
|
11
|
+
|
12
|
+
setup { clear_translations! }
|
13
|
+
|
14
|
+
setup do
|
15
|
+
self.class.controller_class.class_eval do
|
16
|
+
def interpolation_options
|
17
|
+
{
|
18
|
+
:villages_count => 12,
|
19
|
+
:village_name => 'Rhinoceros Town'
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'on a GET to :index' do
|
26
|
+
setup do
|
27
|
+
define_translation 'page.title.villages.index', '{{villages_count}} Villages'
|
28
|
+
get :index
|
29
|
+
end
|
30
|
+
should_set_the_page_title_to '12 Villages'
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'on a GET to :show' do
|
34
|
+
setup do
|
35
|
+
Village.stubs(:find).returns(Village.new('anything'))
|
36
|
+
define_translation 'page.title.villages.show', '{{village_name}}'
|
37
|
+
get :show, :id => 29291
|
38
|
+
end
|
39
|
+
should_set_the_page_title_to 'Rhinoceros Town'
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'that fails to provide a necessary interpolation string' do
|
43
|
+
setup do
|
44
|
+
define_translation 'page.title.villages.new', '{{not_specified_by_the_controller}}'
|
45
|
+
get :new
|
46
|
+
end
|
47
|
+
should "raise a translation error" do
|
48
|
+
assert_raises I18n::MissingInterpolationArgument do
|
49
|
+
@controller.page_title
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/village_model_and_controller'
|
3
|
+
require 'action_view/test_case'
|
4
|
+
|
5
|
+
class RailsIntegrationTest < ActionController::TestCase
|
6
|
+
|
7
|
+
include PageTitleMacros
|
8
|
+
tests VillagesController
|
9
|
+
|
10
|
+
def self.should_expose_as_helper(method)
|
11
|
+
should "expose :#{method} to views as a helper" do
|
12
|
+
helper = Object.new
|
13
|
+
helper.extend VillagesController.master_helper_module
|
14
|
+
assert helper.respond_to?(method)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'a RESTful, titleized controller' do
|
19
|
+
|
20
|
+
should "not have a :page_title action" do
|
21
|
+
assert !VillagesController.action_methods.map { |a| a.to_sym }.include?(:page_title)
|
22
|
+
end
|
23
|
+
|
24
|
+
should_expose_as_helper :page_title
|
25
|
+
should_expose_as_helper :page_title=
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module PageTitleMacros
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.extend PageTitleMacros::ControllerMacros
|
5
|
+
end
|
6
|
+
|
7
|
+
def clear_translations!
|
8
|
+
I18n.reload!
|
9
|
+
end
|
10
|
+
|
11
|
+
def define_translation(key, value)
|
12
|
+
hash = key.to_s.split('.').reverse.inject(value) do |value, key_part|
|
13
|
+
{ key_part.to_sym => value }
|
14
|
+
end
|
15
|
+
I18n.backend.send :merge_translations, I18n.locale, hash
|
16
|
+
end
|
17
|
+
|
18
|
+
def assert_page_title_is(title)
|
19
|
+
assert_equal title, @controller.page_title
|
20
|
+
end
|
21
|
+
|
22
|
+
module ControllerMacros
|
23
|
+
|
24
|
+
def should_set_the_page_title_to(title)
|
25
|
+
should "set the page title to #{title}" do
|
26
|
+
assert_page_title_is title
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/village_model_and_controller'
|
3
|
+
|
4
|
+
class SimpleCustomTitlesTest < ActionController::TestCase
|
5
|
+
include PageTitleMacros
|
6
|
+
tests VillagesController
|
7
|
+
|
8
|
+
context 'a RESTful, titleize controller' do
|
9
|
+
|
10
|
+
context 'with custom page titles set up' do
|
11
|
+
|
12
|
+
setup { clear_translations! }
|
13
|
+
|
14
|
+
context 'on a GET to :index' do
|
15
|
+
setup do
|
16
|
+
define_translation 'page.title.villages.index', 'Some Villages'
|
17
|
+
get :index
|
18
|
+
end
|
19
|
+
should_set_the_page_title_to 'Some Villages'
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'on a GET to :new' do
|
23
|
+
setup do
|
24
|
+
define_translation 'page.title.villages.new', 'Add a Village'
|
25
|
+
get :new
|
26
|
+
end
|
27
|
+
should_set_the_page_title_to "Add a Village"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
test_dir = File.dirname(__FILE__)
|
2
|
+
|
3
|
+
# testing support:
|
4
|
+
require 'test/unit'
|
5
|
+
require 'test/unit/testcase'
|
6
|
+
require 'rubygems'
|
7
|
+
require 'shoulda'
|
8
|
+
gem 'jferris-mocha'
|
9
|
+
require 'mocha'
|
10
|
+
require 'redgreen'
|
11
|
+
|
12
|
+
# set up Rails:
|
13
|
+
ENV["RAILS_ENV"] ||= "test"
|
14
|
+
RAILS_ROOT = "anywhere"
|
15
|
+
require 'active_support'
|
16
|
+
require 'action_controller'
|
17
|
+
require 'action_controller/test_case'
|
18
|
+
require 'action_controller/test_process'
|
19
|
+
I18n.reload!
|
20
|
+
ActionController::Base.view_paths = File.join(File.dirname(__FILE__), 'views')
|
21
|
+
class ApplicationController < ActionController::Base; end
|
22
|
+
|
23
|
+
# load title_estuary:
|
24
|
+
ActiveSupport::Dependencies.load_paths << File.expand_path(File.join(test_dir, '..', 'lib'))
|
25
|
+
require_dependency 'title_estuary'
|
26
|
+
Shoulda.autoload_macros File.join(test_dir, '..')
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Village
|
2
|
+
def initialize(name); @name = name; end
|
3
|
+
def to_s; @name.to_s; end
|
4
|
+
end
|
5
|
+
|
6
|
+
class VillagesController < ActionController::Base
|
7
|
+
include TitleEstuary
|
8
|
+
def index; render :nothing => true; end
|
9
|
+
def burninated; index; end
|
10
|
+
def new; index; end
|
11
|
+
def create; index; end
|
12
|
+
def show; @village = Village.find; index; end
|
13
|
+
def burninate; show; end
|
14
|
+
def edit; show; end
|
15
|
+
def update; show; end
|
16
|
+
def destroy; show; end
|
17
|
+
end
|
18
|
+
|
19
|
+
ActionController::Routing::Routes.draw do |map|
|
20
|
+
map.resources :villages, :collection => { :burninated => :get },
|
21
|
+
:member => { :burninate => :get }
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: title_estuary
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Rosen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-09-02 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Title Estuary speeds up development by giving you good default titles and simple customizability, including internationalization.
|
17
|
+
email: james.a.rosen@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- MIT-LICENSE
|
26
|
+
- README.rdoc
|
27
|
+
- Rakefile
|
28
|
+
- VERSION
|
29
|
+
- lib/title_estuary.rb
|
30
|
+
- lib/title_estuary/inherited_resources_support.rb
|
31
|
+
- tasks/doc.task
|
32
|
+
- tasks/gem.task
|
33
|
+
- tasks/test.task
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://github.com/gcnovus/title_estuary
|
36
|
+
licenses: []
|
37
|
+
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options:
|
40
|
+
- --line-numbers
|
41
|
+
- --inline-source
|
42
|
+
- --title
|
43
|
+
- "Title Estuary: RDoc"
|
44
|
+
- --charset
|
45
|
+
- utf-8
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.3.3
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: Easy, internationalized page titles
|
67
|
+
test_files:
|
68
|
+
- test/default_titles_test.rb
|
69
|
+
- test/dynamic_page_title_test.rb
|
70
|
+
- test/inherited_resources_integration_test.rb
|
71
|
+
- test/interpolated_page_titles_test.rb
|
72
|
+
- test/rails_integration_test.rb
|
73
|
+
- test/shoulda_macros/page_title_macros.rb
|
74
|
+
- test/simple_custom_titles_test.rb
|
75
|
+
- test/test_helper.rb
|
76
|
+
- test/village_model_and_controller.rb
|