metaslug 0.3.3
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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/Gemfile +6 -0
- data/MIT-LICENSE +20 -0
- data/README.md +112 -0
- data/Rakefile +19 -0
- data/lib/metaslug/controllers/action_controller_extension.rb +165 -0
- data/lib/metaslug/helpers/action_view_extension.rb +49 -0
- data/lib/metaslug/hooks.rb +15 -0
- data/lib/metaslug/railtie.rb +7 -0
- data/lib/metaslug/version.rb +3 -0
- data/lib/metaslug.rb +7 -0
- data/lib/rails/generators/metaslug/install/install_generator.rb +21 -0
- data/lib/rails/generators/metaslug/locale/locale_generator.rb +69 -0
- data/lib/tasks/metaslug_tasks.rake +4 -0
- data/metaslug.gemspec +24 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/assets/stylesheets/scaffold.css +56 -0
- data/test/dummy/app/controllers/application_controller.rb +13 -0
- data/test/dummy/app/controllers/categories_controller.rb +58 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/controllers/pages_controller.rb +12 -0
- data/test/dummy/app/controllers/posts_controller.rb +60 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/helpers/categories_helper.rb +2 -0
- data/test/dummy/app/helpers/metaslug_helper.rb +2 -0
- data/test/dummy/app/helpers/pages_helper.rb +2 -0
- data/test/dummy/app/helpers/posts_helper.rb +2 -0
- data/test/dummy/app/mailers/.keep +0 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/category.rb +3 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/models/page.rb +3 -0
- data/test/dummy/app/models/post.rb +5 -0
- data/test/dummy/app/views/categories/_form.html.erb +21 -0
- data/test/dummy/app/views/categories/edit.html.erb +6 -0
- data/test/dummy/app/views/categories/index.html.erb +25 -0
- data/test/dummy/app/views/categories/new.html.erb +5 -0
- data/test/dummy/app/views/categories/show.html.erb +9 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/pages/show.html.erb +1 -0
- data/test/dummy/app/views/posts/_form.html.erb +33 -0
- data/test/dummy/app/views/posts/edit.html.erb +6 -0
- data/test/dummy/app/views/posts/index.html.erb +31 -0
- data/test/dummy/app/views/posts/new.html.erb +5 -0
- data/test/dummy/app/views/posts/show.html.erb +24 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.example.yml +22 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +82 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/assets.rb +8 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/initializer.rb +1 -0
- data/test/dummy/config/initializers/metaslug.rb +1 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/de.yml +2 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/locales/fr.yml +23 -0
- data/test/dummy/config/metaslug/de.yml +4 -0
- data/test/dummy/config/metaslug/en.yml +61 -0
- data/test/dummy/config/metaslug/fr.yml +41 -0
- data/test/dummy/config/routes.rb +12 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/migrate/20140924091048_create_posts.rb +12 -0
- data/test/dummy/db/migrate/20140924091105_create_categories.rb +9 -0
- data/test/dummy/db/migrate/20140925101545_create_pages.rb +11 -0
- data/test/dummy/db/migrate/20140929145421_add_title_and_description_to_page.rb +6 -0
- data/test/dummy/db/schema.rb +43 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/test/fixtures/categories.yml +7 -0
- data/test/dummy/test/fixtures/pages.yml +23 -0
- data/test/dummy/test/fixtures/posts.yml +13 -0
- data/test/dummy/test/helpers/metaslug_helper_test.rb +25 -0
- data/test/dummy/test/integration/metas_test.rb +91 -0
- data/test/metaslug_test.rb +5 -0
- data/test/test_helper.rb +30 -0
- metadata +274 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5b1af058704bc625b6355a1c6ecf062f4d66e5bc
|
4
|
+
data.tar.gz: ce0ee9bb641e9f0a229bd9a417ab82768092d22c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7d67b7081bade2b06be9c5dd3c30bdd2d55ec258b583a3b423fb83a4ac5fb3c293733f6d2ed6f530944598344b580fd3594500598ace30cda95ed751eadc5133
|
7
|
+
data.tar.gz: dd0dbfd64162c81889557a93c9365d4a4fe280f60589b19a66981567409960d8f0c18b6cf5a4384ed0d72cf74f9345becd9a49b0aff516615da49d44783246bc
|
data/.gitignore
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
.bundle/
|
2
|
+
.config
|
3
|
+
.yardoc
|
4
|
+
log/*.log
|
5
|
+
pkg/
|
6
|
+
test/dummy/db/*.sqlite3
|
7
|
+
test/dummy/db/*.sqlite3-journal
|
8
|
+
test/dummy/log/*.log
|
9
|
+
test/dummy/tmp/
|
10
|
+
test/dummy/.sass-cache
|
11
|
+
test/dummy/config/database.yml
|
12
|
+
test/dummy/config/secrets.yml
|
13
|
+
vendor/bundle
|
14
|
+
Gemfile.lock
|
15
|
+
*.gem
|
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 YOURNAME
|
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.md
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# Metaslug
|
2
|
+
|
3
|
+
Metaslug allows you to map url to metas by locale.
|
4
|
+
You can define slug '/awesome-page' will have title 'Awesome' with other custom metas.
|
5
|
+
|
6
|
+
Metaslug uses liquid to be able to add dynamic content in the metas.
|
7
|
+
|
8
|
+
## Starting
|
9
|
+
|
10
|
+
First add the `metaslug` helper in your layout then use the install generator:
|
11
|
+
|
12
|
+
~~~
|
13
|
+
doctype html
|
14
|
+
html lang="fr"
|
15
|
+
head
|
16
|
+
meta charset="utf-8"
|
17
|
+
= metaslug
|
18
|
+
~~~
|
19
|
+
|
20
|
+
~~~
|
21
|
+
bundle exec rails generate metaslug:install
|
22
|
+
~~~
|
23
|
+
|
24
|
+
It will create the `config/metaslug` folder and add an initializer.
|
25
|
+
Locale files should be presents in this directory, but there is a task to help you generating them using your defined routes.
|
26
|
+
|
27
|
+
~~~
|
28
|
+
bundle exec rails generate metaslug:locale
|
29
|
+
~~~
|
30
|
+
|
31
|
+
It will generate files like:
|
32
|
+
|
33
|
+
~~~
|
34
|
+
en:
|
35
|
+
default:
|
36
|
+
description: "Default description"
|
37
|
+
title: "Default title"
|
38
|
+
"/posts":
|
39
|
+
description: ""
|
40
|
+
title: ""
|
41
|
+
"/posts/:id/edit":
|
42
|
+
description: ""
|
43
|
+
title: ""
|
44
|
+
~~~
|
45
|
+
|
46
|
+
This generator takes options. For example:
|
47
|
+
|
48
|
+
~~~
|
49
|
+
bundle exec rails g metaslug:locale -l eueui -o -m description,keywords,title
|
50
|
+
~~~
|
51
|
+
|
52
|
+
will take generate a file for de locale. `-o` specifies to only print content on the console while `-m` takes your metas (defaults are title and description).
|
53
|
+
|
54
|
+
On development mode, translations are reloaded for each request, not in the other environments.
|
55
|
+
|
56
|
+
You can edit your locale file to add static or dynamic content.
|
57
|
+
|
58
|
+
~~~
|
59
|
+
en:
|
60
|
+
default:
|
61
|
+
description: "Default description"
|
62
|
+
title: "Default title"
|
63
|
+
"/my-page":
|
64
|
+
description: ""
|
65
|
+
title: "Title"
|
66
|
+
"/posts/:id/edit":
|
67
|
+
description: "Edit a post"
|
68
|
+
title: "Edit post with title {{post.title}}"
|
69
|
+
~~~
|
70
|
+
|
71
|
+
We use liquid templates to be able to add dynamic content, based on your vars.
|
72
|
+
All you have to do is to allow methods in your model, and add allow variable in your controllers (they must be instance variable).
|
73
|
+
`metaslug_vars` is just a before_filter and can take the exact same options, like only, except…
|
74
|
+
|
75
|
+
~~~
|
76
|
+
class Post < ActiveRecord::Base
|
77
|
+
liquid_methods :title
|
78
|
+
end
|
79
|
+
~~~
|
80
|
+
|
81
|
+
~~~
|
82
|
+
class PostsController < ApplicationController
|
83
|
+
before_action :set_post, only: [:show, :edit, :update, :destroy]
|
84
|
+
metaslug_vars :post, only: :edit
|
85
|
+
|
86
|
+
private
|
87
|
+
def set_post
|
88
|
+
@post = Post.find(params[:id])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
~~~
|
92
|
+
|
93
|
+
## Tests
|
94
|
+
|
95
|
+
You can run the integration tests using:
|
96
|
+
|
97
|
+
~~~
|
98
|
+
bundle exec rake test
|
99
|
+
~~~
|
100
|
+
|
101
|
+
## Warning
|
102
|
+
|
103
|
+
Metaslug overrides the default render method, to be able to use dynamic metas.
|
104
|
+
We need to access the vars setted after action and interpolate them before rendering.
|
105
|
+
|
106
|
+
## Roadmap
|
107
|
+
|
108
|
+
This is what we planned to add next:
|
109
|
+
|
110
|
+
- Different storage (database, cache…)
|
111
|
+
- Web interface to edit metas from the app
|
112
|
+
- Remove rails dependency
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
|
+
|
9
|
+
require 'rake/testtask'
|
10
|
+
|
11
|
+
Rake::TestTask.new(:test) do |t|
|
12
|
+
t.libs << 'lib'
|
13
|
+
t.libs << 'test'
|
14
|
+
t.pattern = 'test/**/*_test.rb'
|
15
|
+
t.verbose = false
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
task default: :test
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module Metaslug
|
2
|
+
module ActionControllerExtension
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
|
6
|
+
#
|
7
|
+
# Initialise the traduction hash, load every metas into it.
|
8
|
+
# We only do this once, unless it is the development environment.
|
9
|
+
#
|
10
|
+
# @return [void] [Load metas of the current page]
|
11
|
+
def load_metas_for_current_slug
|
12
|
+
# initialize storage to an empty Hash, unless already exists
|
13
|
+
initialize_metas_storage
|
14
|
+
load_all_metas if Rails.env.development? or metas_storage.empty?
|
15
|
+
set_metas_for_current_path
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# A locale corresponds to a YAML file. We load each YAML file individually
|
20
|
+
# then merge then into a global hash.
|
21
|
+
#
|
22
|
+
# @return [Hash] [Global hash with all metas]
|
23
|
+
def load_all_metas
|
24
|
+
Thread.current[:metas] = I18n.available_locales.inject({}) do |acc, locale|
|
25
|
+
acc.merge!(load_metas_for_locale(locale))
|
26
|
+
acc
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Load a YAML file corresponding to a locale after ensuring it exists.
|
32
|
+
# @param locale [Symbol] [Locale]
|
33
|
+
#
|
34
|
+
# @return [Hash] [Metas]
|
35
|
+
def load_metas_for_locale(locale)
|
36
|
+
path = metas_path(locale)
|
37
|
+
if File.exists?(path)
|
38
|
+
YAML.load(File.open(path))
|
39
|
+
else
|
40
|
+
logger.error "[Metaslug] #{path} not found."
|
41
|
+
{}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Search and load metas of the current path.
|
47
|
+
#
|
48
|
+
# @return [void]
|
49
|
+
def set_metas_for_current_path
|
50
|
+
locale_metas_storage.keys.each do |k|
|
51
|
+
if request.path.match(translate_key_into_regexp(k))
|
52
|
+
set_metas_from_hash(locale_metas_storage[k])
|
53
|
+
return
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# if no key match the current path, load default metas if present.
|
58
|
+
if locale_metas_storage.has_key?('default')
|
59
|
+
set_metas_from_hash(locale_metas_storage['default'])
|
60
|
+
else
|
61
|
+
set_metas_from_hash({})
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Load metas into an instance variable to have access to them in the helper.
|
67
|
+
# Get the instance variables mark as accessible in the before_filter to interpolate
|
68
|
+
# values in the liquid template.
|
69
|
+
# @param values [Hash] [Metas]
|
70
|
+
#
|
71
|
+
# @return [Hash] [Metas]
|
72
|
+
def set_metas_from_hash(values)
|
73
|
+
@metaslug_vars ||= []
|
74
|
+
# For each meta we need to interpole the value if it use a dynamic content.
|
75
|
+
values.each do |k ,v|
|
76
|
+
if v.is_a?(Hash)
|
77
|
+
# recursive call for nested hash like { 'og' => { 'locale' => { 'alternate' => 'fr_FR' } } }
|
78
|
+
set_metas_from_hash(v)
|
79
|
+
else
|
80
|
+
# Looks like a liquid template
|
81
|
+
if v =~ /{{.*}}/
|
82
|
+
if @metaslug_vars.empty?
|
83
|
+
Rails.logger.debug "You provide a template but don't set access to your vars in the associated controller."
|
84
|
+
values[k] = v
|
85
|
+
else
|
86
|
+
template = Liquid::Template.parse(v)
|
87
|
+
h = @metaslug_vars.inject({}) do |acc, v|
|
88
|
+
acc[v.to_s] = instance_variable_get("@#{v}")
|
89
|
+
acc
|
90
|
+
end
|
91
|
+
values[k] = template.render(h)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
@metaslug = values
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# Return path of the YAML file of this locale.
|
101
|
+
# @param locale [Symbol] [Locale]
|
102
|
+
#
|
103
|
+
# @return [Pathname] [Path of the YAML file]
|
104
|
+
def metas_path(locale)
|
105
|
+
# TODO: Let user configure it.
|
106
|
+
Rails.root.join('config', 'metaslug', "#{locale}.yml")
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Metas of the given locale
|
111
|
+
# @param locale = I18n.locale [Symbol] [Locale]
|
112
|
+
#
|
113
|
+
# @return [Hash] [Metas]
|
114
|
+
def locale_metas_storage(locale = I18n.locale)
|
115
|
+
metas_storage[I18n.locale.to_s]
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
# Backend storage of the metas. We store it in the current thread to avoid
|
120
|
+
# reloading it.
|
121
|
+
#
|
122
|
+
# @return [Hash] [Global metas]
|
123
|
+
def metas_storage
|
124
|
+
Thread.current[:metas]
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# Initialize storage to an empty hash, unless already set.
|
129
|
+
#
|
130
|
+
# @return [Hash] [Global metas]
|
131
|
+
def initialize_metas_storage
|
132
|
+
Thread.current[:metas] ||= {}
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# YAML entries may looks like routes, like /categories/:id/edit. To be able
|
137
|
+
# to test these entries, we convert them to regexp, replacing :id (and others sym)
|
138
|
+
# @param k [String] [key]
|
139
|
+
#
|
140
|
+
# @return [Regexp] [Builded regexp]
|
141
|
+
def translate_key_into_regexp(k)
|
142
|
+
# replace :id with regular expression
|
143
|
+
%r{^#{k.gsub /\:\w+/, '[a-z0-9_.-]+'}$}i
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.metaslug_vars(*args)
|
147
|
+
before_filter args.extract_options! do
|
148
|
+
@metaslug_vars = args
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# Overriding the default render method because we need to use the action
|
154
|
+
# variables to render the liquid template. This had to be done after the
|
155
|
+
# action and before the render.
|
156
|
+
# @param *args [Array] [Default arguments]
|
157
|
+
#
|
158
|
+
# @return [type] [description]
|
159
|
+
def render(*args)
|
160
|
+
load_metas_for_current_slug
|
161
|
+
super
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Metaslug
|
2
|
+
module ActionViewExtension
|
3
|
+
def metaslug
|
4
|
+
@metaslug.inject([]) do |acc, (k, v)|
|
5
|
+
if 'title' == k.to_s
|
6
|
+
acc << content_tag(:title, @metaslug['title'])
|
7
|
+
elsif v.is_a?(Hash)
|
8
|
+
# more complicated metas, like property
|
9
|
+
set_metas_from_hash(v, k, acc)
|
10
|
+
else
|
11
|
+
acc << content_tag(:meta, nil, { name: k.to_s, content: @metaslug[k.to_s] })
|
12
|
+
end
|
13
|
+
acc
|
14
|
+
end.join.html_safe
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
#
|
19
|
+
# Recursive function to build metas and add them to the accumulator.
|
20
|
+
# @param hash [Hash] [Hash of the metas]
|
21
|
+
# @param key [String] [Key of the parent hash]
|
22
|
+
# @param acc [Array] [Metas accumulator]
|
23
|
+
# @param separator = ':' [String] [Separator used when building key, ex: og:title]
|
24
|
+
#
|
25
|
+
# @return [type] [description]
|
26
|
+
def set_metas_from_hash(hash, key, acc, separator = ':')
|
27
|
+
hash.each do |k, v|
|
28
|
+
if v.is_a?(Hash)
|
29
|
+
_k = build_meta_name(key, k, separator)
|
30
|
+
set_metas_from_hash(v, _k, acc)
|
31
|
+
else
|
32
|
+
_k = build_meta_name(key, k, separator)
|
33
|
+
acc << content_tag(:meta, nil, { property: _k, content: v })
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Construct meta name based on the previous keys
|
40
|
+
# @param base_key [String] [Key of the parent hash, ex: og]
|
41
|
+
# @param key [String] [Key of the actual hash, ex: title]
|
42
|
+
# @param separator = ':' [String] [Separator used when building key, ex: og:title]
|
43
|
+
#
|
44
|
+
# @return [type] [description]
|
45
|
+
def build_meta_name(base_key, key, separator = ':')
|
46
|
+
base_key.present? ? "#{base_key}#{separator}#{key}" : key
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Metaslug
|
2
|
+
class Hooks
|
3
|
+
def self.init
|
4
|
+
ActiveSupport.on_load(:action_controller) do
|
5
|
+
require 'metaslug/controllers/action_controller_extension'
|
6
|
+
::ActionController::Base.send :include, Metaslug::ActionControllerExtension
|
7
|
+
end
|
8
|
+
|
9
|
+
ActiveSupport.on_load(:action_view) do
|
10
|
+
require 'metaslug/helpers/action_view_extension'
|
11
|
+
::ActionView::Base.send :include, Metaslug::ActionViewExtension
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/metaslug.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Metaslug
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
def self.banner
|
5
|
+
<<-BANNER.chomp
|
6
|
+
rails generate metaslug:install
|
7
|
+
|
8
|
+
Create locale's folder and initializer.
|
9
|
+
BANNER
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_locales_folder
|
13
|
+
empty_directory "config/metaslug"
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_install_file
|
17
|
+
create_file "config/initializers/metaslug.rb", "require 'liquid'"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Metaslug
|
2
|
+
module Generators
|
3
|
+
class LocaleGenerator < Rails::Generators::Base
|
4
|
+
class_option :locale, type: :string, aliases: '-l', desc: "Generate a locale file base on the routes."
|
5
|
+
class_option :output, type: :string, aliases: '-o', desc: "Do not create file, just output buffer."
|
6
|
+
class_option :metas, type: :string, aliases: '-m', desc: "Define the metas you want to use."
|
7
|
+
|
8
|
+
def self.banner
|
9
|
+
<<-BANNER.chomp
|
10
|
+
rails generate metaslug:locale
|
11
|
+
|
12
|
+
Try to generate the metas file of the given locale, based on the current routes.
|
13
|
+
BANNER
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_locale_file
|
17
|
+
routes = get_paths_from_routes
|
18
|
+
|
19
|
+
locales = options.locale? ?
|
20
|
+
[options.locale] :
|
21
|
+
I18n.available_locales
|
22
|
+
|
23
|
+
metas = options.metas? ?
|
24
|
+
options.metas.split(',') :
|
25
|
+
["description", "title"]
|
26
|
+
|
27
|
+
locales.each do |locale|
|
28
|
+
buffer = "#{locale}:\n"
|
29
|
+
add_metas_to_buffer(buffer, 'default', { quote_section: false }, *metas)
|
30
|
+
|
31
|
+
routes.each do |route|
|
32
|
+
add_metas_to_buffer(buffer, route, { quote_section: true }, *metas)
|
33
|
+
end
|
34
|
+
|
35
|
+
if options.output?
|
36
|
+
$stdout.puts buffer
|
37
|
+
else
|
38
|
+
create_file "config/metaslug/#{locale}.yml", buffer
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def add_metas_to_buffer(buffer, section, options = {}, *args)
|
45
|
+
spaces = ' ' * 2
|
46
|
+
if options[:quote_section]
|
47
|
+
buffer << "#{spaces}\"#{section}\":\n"
|
48
|
+
else
|
49
|
+
buffer << "#{spaces}#{section}:\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
args.each do |meta|
|
53
|
+
buffer << "#{spaces * 2}\"#{meta}\": \"\"\n"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_paths_from_routes
|
58
|
+
Rails.application.routes.routes.map do |route|
|
59
|
+
path = route.path.spec.to_s
|
60
|
+
# only keep GET url
|
61
|
+
next unless "GET".match route.verb.to_s
|
62
|
+
next if path.starts_with?('/assets') or path.starts_with?('/rails')
|
63
|
+
# remove (.:format), this is a bit dirty
|
64
|
+
$1 if path.match /(.*)\(.*/
|
65
|
+
end.compact.uniq
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/metaslug.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
require "metaslug/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "metaslug"
|
7
|
+
s.version = Metaslug::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Martin Catty"]
|
10
|
+
s.email = ["mcatty@synbioz.com"]
|
11
|
+
s.homepage = "https://github.com/synbioz/metaslug"
|
12
|
+
s.summary = "Set metas according to a path."
|
13
|
+
s.description = "Metaslug allows you to set your metas information in a localized YAML file."
|
14
|
+
s.license = "MIT"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
|
19
|
+
s.add_dependency "rails", "~> 4.0"
|
20
|
+
s.add_dependency "liquid"
|
21
|
+
|
22
|
+
s.add_development_dependency "capybara"
|
23
|
+
s.add_development_dependency "sqlite3"
|
24
|
+
end
|
data/test/dummy/Rakefile
ADDED
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
11
|
+
* file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,56 @@
|
|
1
|
+
body { background-color: #fff; color: #333; }
|
2
|
+
|
3
|
+
body, p, ol, ul, td {
|
4
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
5
|
+
font-size: 13px;
|
6
|
+
line-height: 18px;
|
7
|
+
}
|
8
|
+
|
9
|
+
pre {
|
10
|
+
background-color: #eee;
|
11
|
+
padding: 10px;
|
12
|
+
font-size: 11px;
|
13
|
+
}
|
14
|
+
|
15
|
+
a { color: #000; }
|
16
|
+
a:visited { color: #666; }
|
17
|
+
a:hover { color: #fff; background-color:#000; }
|
18
|
+
|
19
|
+
div.field, div.actions {
|
20
|
+
margin-bottom: 10px;
|
21
|
+
}
|
22
|
+
|
23
|
+
#notice {
|
24
|
+
color: green;
|
25
|
+
}
|
26
|
+
|
27
|
+
.field_with_errors {
|
28
|
+
padding: 2px;
|
29
|
+
background-color: red;
|
30
|
+
display: table;
|
31
|
+
}
|
32
|
+
|
33
|
+
#error_explanation {
|
34
|
+
width: 450px;
|
35
|
+
border: 2px solid red;
|
36
|
+
padding: 7px;
|
37
|
+
padding-bottom: 0;
|
38
|
+
margin-bottom: 20px;
|
39
|
+
background-color: #f0f0f0;
|
40
|
+
}
|
41
|
+
|
42
|
+
#error_explanation h2 {
|
43
|
+
text-align: left;
|
44
|
+
font-weight: bold;
|
45
|
+
padding: 5px 5px 5px 15px;
|
46
|
+
font-size: 12px;
|
47
|
+
margin: -7px;
|
48
|
+
margin-bottom: 0px;
|
49
|
+
background-color: #c00;
|
50
|
+
color: #fff;
|
51
|
+
}
|
52
|
+
|
53
|
+
#error_explanation ul li {
|
54
|
+
font-size: 12px;
|
55
|
+
list-style: square;
|
56
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ApplicationController < ActionController::Base
|
2
|
+
# Prevent CSRF attacks by raising an exception.
|
3
|
+
# For APIs, you may want to use :null_session instead.
|
4
|
+
protect_from_forgery with: :exception
|
5
|
+
prepend_before_filter :set_locale
|
6
|
+
|
7
|
+
private
|
8
|
+
def set_locale
|
9
|
+
if I18n.available_locales.map(&:to_s).include?(params[:locale])
|
10
|
+
I18n.locale = params[:locale]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|