radiant-tags-extension 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/HELP.md +50 -0
- data/HELP_admin.md +30 -0
- data/README +38 -0
- data/Rakefile +25 -0
- data/app/models/meta_tag.rb +53 -0
- data/app/models/radius_tags.rb +328 -0
- data/app/models/tag_search_page.rb +87 -0
- data/app/models/tagging.rb +10 -0
- data/app/views/admin/help/_using_tags.html.haml +4 -0
- data/app/views/admin/pages/_tag_field.html.haml +8 -0
- data/db/migrate/001_add_tag_support.rb +20 -0
- data/lib/tagging_methods.rb +128 -0
- data/lib/tasks/tags_extension_tasks.rake +32 -0
- data/public/stylesheets/tags.css +11 -0
- data/tags_extension.rb +57 -0
- data/test/fixtures/meta_tags.yml +12 -0
- data/test/fixtures/page_parts.yml +17 -0
- data/test/fixtures/pages.yml +43 -0
- data/test/fixtures/taggings.yml +20 -0
- data/test/functional/tag_search_page_test.rb +44 -0
- data/test/functional/tags_extension_test.rb +19 -0
- data/test/helpers/render_test_helper.rb +60 -0
- data/test/test_helper.rb +20 -0
- data/test/unit/page_taggability_test.rb +20 -0
- data/vendor/plugins/has_many_polymorphs/.gitignore +1 -0
- data/vendor/plugins/has_many_polymorphs/CHANGELOG +86 -0
- data/vendor/plugins/has_many_polymorphs/LICENSE +184 -0
- data/vendor/plugins/has_many_polymorphs/Manifest +173 -0
- data/vendor/plugins/has_many_polymorphs/README +205 -0
- data/vendor/plugins/has_many_polymorphs/Rakefile +28 -0
- data/vendor/plugins/has_many_polymorphs/TODO +2 -0
- data/vendor/plugins/has_many_polymorphs/examples/hmph.rb +69 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/tagging_generator.rb +97 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/migration.rb +28 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tag.rb +39 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tag_test.rb +15 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tagging.rb +16 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tagging_extensions.rb +203 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tagging_test.rb +85 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/taggings.yml +23 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tags.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/init.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/association.rb +160 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/autoload.rb +69 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/base.rb +60 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/class_methods.rb +600 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/configuration.rb +19 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/debugging_tools.rb +103 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/rake_task_redefine_task.rb +35 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/reflection.rb +58 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/support_methods.rb +88 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs.rb +27 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/bow_wows.yml +10 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/cats.yml +18 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/eaters_foodstuffs.yml +0 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/fish.yml +12 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/frogs.yml +5 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/keep_your_enemies_close.yml +0 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/little_whale_pupils.yml +0 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/people.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/petfoods.yml +11 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/whales.yml +5 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/wild_boars.yml +10 -0
- data/vendor/plugins/has_many_polymorphs/test/generator/tagging_generator_test.rb +42 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/README +182 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/Rakefile +19 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/controllers/application.rb +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/controllers/bones_controller.rb +5 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/addresses_helper.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/application_helper.rb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/bones_helper.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/sellers_helper.rb +28 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/states_helper.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/users_helper.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/bone.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/double_sti_parent.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/double_sti_parent_relationship.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/organic_substance.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/single_sti_parent.rb +4 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/single_sti_parent_relationship.rb +4 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/stick.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/stone.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/addresses/edit.html.erb +12 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/addresses/index.html.erb +18 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/addresses/new.html.erb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/addresses/show.html.erb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/bones/index.rhtml +5 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/layouts/addresses.html.erb +17 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/layouts/sellers.html.erb +17 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/layouts/states.html.erb +17 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/layouts/users.html.erb +17 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/sellers/edit.html.erb +12 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/sellers/index.html.erb +20 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/sellers/new.html.erb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/sellers/show.html.erb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/states/edit.html.erb +12 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/states/index.html.erb +19 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/states/new.html.erb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/states/show.html.erb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/users/edit.html.erb +12 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/users/index.html.erb +22 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/users/new.html.erb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/users/show.html.erb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/boot.rb +110 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/database.yml +17 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/environment.rb +19 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/environment.rb.canonical +19 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/environments/development.rb +9 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/environments/production.rb +18 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/environments/test.rb +19 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/locomotive.yml +6 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/routes.rb +33 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/ultrasphinx/default.base +56 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/ultrasphinx/development.conf.canonical +155 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/001_create_sticks.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/002_create_stones.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/003_create_organic_substances.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/004_create_bones.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/005_create_single_sti_parents.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/006_create_double_sti_parents.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/007_create_single_sti_parent_relationships.rb +13 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/008_create_double_sti_parent_relationships.rb +14 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/009_create_library_model.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/doc/README_FOR_APP +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/generators/commenting_generator_test.rb +83 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/lib/library_model.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/.htaccess +40 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/404.html +30 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/500.html +30 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/dispatch.cgi +10 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/dispatch.fcgi +24 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/dispatch.rb +10 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/favicon.ico +0 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/images/rails.png +0 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/index.html +277 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/javascripts/application.js +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/javascripts/controls.js +833 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/javascripts/dragdrop.js +942 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/javascripts/effects.js +1088 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/javascripts/prototype.js +2515 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/robots.txt +1 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/stylesheets/scaffold.css +74 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/about +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/breakpointer +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/console +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/destroy +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/generate +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/performance/benchmarker +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/performance/profiler +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/plugin +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/process/inspector +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/process/reaper +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/process/spawner +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/runner +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/server +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/double_sti_parent_relationships.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/double_sti_parents.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/organic_substances.yml +5 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/single_sti_parent_relationships.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/single_sti_parents.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/sticks.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/stones.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/functional/addresses_controller_test.rb +57 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/functional/bones_controller_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/functional/sellers_controller_test.rb +57 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/functional/states_controller_test.rb +57 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/functional/users_controller_test.rb +57 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/test_helper.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/bone_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/double_sti_parent_relationship_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/double_sti_parent_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/organic_substance_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/single_sti_parent_relationship_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/single_sti_parent_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/stick_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/stone_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/server_test.rb +43 -0
- data/vendor/plugins/has_many_polymorphs/test/models/aquatic/fish.rb +5 -0
- data/vendor/plugins/has_many_polymorphs/test/models/aquatic/pupils_whale.rb +7 -0
- data/vendor/plugins/has_many_polymorphs/test/models/aquatic/whale.rb +15 -0
- data/vendor/plugins/has_many_polymorphs/test/models/beautiful_fight_relationship.rb +26 -0
- data/vendor/plugins/has_many_polymorphs/test/models/canine.rb +9 -0
- data/vendor/plugins/has_many_polymorphs/test/models/cat.rb +5 -0
- data/vendor/plugins/has_many_polymorphs/test/models/dog.rb +18 -0
- data/vendor/plugins/has_many_polymorphs/test/models/eaters_foodstuff.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/models/frog.rb +4 -0
- data/vendor/plugins/has_many_polymorphs/test/models/kitten.rb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/models/parentship.rb +4 -0
- data/vendor/plugins/has_many_polymorphs/test/models/person.rb +9 -0
- data/vendor/plugins/has_many_polymorphs/test/models/petfood.rb +39 -0
- data/vendor/plugins/has_many_polymorphs/test/models/tabby.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/models/wild_boar.rb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/modules/extension_module.rb +9 -0
- data/vendor/plugins/has_many_polymorphs/test/modules/other_extension_module.rb +9 -0
- data/vendor/plugins/has_many_polymorphs/test/patches/symlinked_plugins_1.2.6.diff +46 -0
- data/vendor/plugins/has_many_polymorphs/test/schema.rb +87 -0
- data/vendor/plugins/has_many_polymorphs/test/setup.rb +14 -0
- data/vendor/plugins/has_many_polymorphs/test/test_helper.rb +52 -0
- data/vendor/plugins/has_many_polymorphs/test/unit/has_many_polymorphs_test.rb +713 -0
- metadata +421 -0
data/HELP.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
The Tags extension provides a way for you to easily categorize your pages.
|
2
|
+
|
3
|
+
== Results page
|
4
|
+
|
5
|
+
<r:search:empty>
|
6
|
+
<h2>I couldn't find anything tagged with "<r:search:query/>".</h2>
|
7
|
+
</r:search:empty>
|
8
|
+
|
9
|
+
<r:search:results>
|
10
|
+
<h2>Found the following pages that are tagged with "<em><r:search:query/></em>".</h2>
|
11
|
+
|
12
|
+
<ul>
|
13
|
+
<r:search:results:each>
|
14
|
+
<li><r:link/> - <r:author/> - <r:date/></li>
|
15
|
+
</r:search:results:each>
|
16
|
+
</ul>
|
17
|
+
</r:search:results>
|
18
|
+
|
19
|
+
|
20
|
+
== Tag cloud
|
21
|
+
|
22
|
+
Use `<r:tag_cloud />` anywhere you like.
|
23
|
+
I made a stab at building the 'perfect' tag cloud markup, as inspired by a post on 24ways.org; http://24ways.org/2006/marking-up-a-tag-cloud
|
24
|
+
|
25
|
+
== Tag list
|
26
|
+
|
27
|
+
Use `<r:tag_list />` to get a list of tags for the current page.
|
28
|
+
Also works through children:each.
|
29
|
+
|
30
|
+
== All tags
|
31
|
+
|
32
|
+
Use `<r:all_tags />` to get a list of all tags. You may iterate through them with
|
33
|
+
`<r:all_tags:each>` and access their associated pages with `<r:all_tags:each:pages:each>`
|
34
|
+
|
35
|
+
== Collections
|
36
|
+
|
37
|
+
You can grab a collection of pages with a certain tag like so;
|
38
|
+
|
39
|
+
<r:tagged with="sometag" [scope="/some/page"] [with_any="true"]>
|
40
|
+
<r:link />
|
41
|
+
</r:tagged>
|
42
|
+
|
43
|
+
Which would iterate over all the resulting pages, like you do with children:each.
|
44
|
+
When you define scope, only this page and any of it's (grand)children will be used.
|
45
|
+
Using scope="current_page" will use the page that is currently being rendered as scope.
|
46
|
+
You can also set limit, offset etc like with children:each.
|
47
|
+
|
48
|
+
Using r:tagged in it's default setting searches for pages that have all of the given tags.
|
49
|
+
Using r:tagged with the attribute 'with_any' set to 'true' will find pages that have any of
|
50
|
+
the given tags.
|
data/HELP_admin.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
The Tags extension allows you to configure the style of tagging between 2 options:
|
2
|
+
simple or complex strings.
|
3
|
+
|
4
|
+
== Simple Tagging
|
5
|
+
|
6
|
+
By default you may add tags to a page in a string such as "this that other". That string
|
7
|
+
will be parsed and turned into 3 separate tags.
|
8
|
+
|
9
|
+
== Complex Tagging
|
10
|
+
|
11
|
+
You may set `Radiant::Config['tags.complex_strings'] = true` to allow you to enter more
|
12
|
+
complex tags for your pages.
|
13
|
+
|
14
|
+
When this setting is `true` the tags are delimited by a semi-colon, allowing you to enter
|
15
|
+
a string of tags such as "My Summer Vacation (2008); Entertainment/Nonsense; Miscellaneous 2.0".
|
16
|
+
The result of that string will return 3 tags: `My Summer Vacation (2008)`,
|
17
|
+
`Entertainment/Nonsense` and 'Miscellaneous 2.0'
|
18
|
+
|
19
|
+
== Making the choice
|
20
|
+
|
21
|
+
You'll need to restart the application server after changing this setting. Please keep in
|
22
|
+
mind that any changes to this setting may affect any tags you currently have in the database.
|
23
|
+
It is recommended that you choose either Simple or Complex, but that you do not switch
|
24
|
+
after creating your tags.
|
25
|
+
|
26
|
+
== Tag Clouds
|
27
|
+
|
28
|
+
Some styles are provided in tags.css for the <r:tag_cloud>. To use it, add this to your layout:
|
29
|
+
|
30
|
+
<link rel="stylesheet" type="text/css" href="/stylesheets/tags.css" />
|
data/README
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
= Tags extension
|
2
|
+
|
3
|
+
Created by: Keith Bingman - keithbingman.com
|
4
|
+
Revived by: Benny Degezelle - gorilla-webdesign.be
|
5
|
+
New features by: Jim Gay - saturnflyer.com
|
6
|
+
Version: 1.5
|
7
|
+
|
8
|
+
This extension enhances the page model with tagging capabilities, tagging as in "2.0" and tagclouds.
|
9
|
+
|
10
|
+
== Requirements
|
11
|
+
|
12
|
+
This extension depends on the has_many_polymorphs plugin (included in vendor/plugins)
|
13
|
+
If you're still on Radiant pre-0.6.7, then the shards_extension should be installed and loaded first.
|
14
|
+
You can change the load order of extensions in config/environment.rb (see http://wiki.radiantcms.org/Using_the_Shards_Extension).
|
15
|
+
|
16
|
+
== Installation
|
17
|
+
|
18
|
+
1. Copy the extension to your vendor/extensions directory as you would any other extension.
|
19
|
+
2. Run 'rake radiant:extensions:tags:install'
|
20
|
+
3. Make a page to sit in /search/by-tag, and give it the "Tag Search" pagetype.
|
21
|
+
If you want to change this location, it's in Radiant::Config['tags.results_page_url'].
|
22
|
+
|
23
|
+
Done!
|
24
|
+
Here's a sample results page to get you started;
|
25
|
+
|
26
|
+
<r:search:empty>
|
27
|
+
<h2>I couldn't find anything tagged with "<r:search:query/>".</h2>
|
28
|
+
</r:search:empty>
|
29
|
+
|
30
|
+
<r:search:results>
|
31
|
+
<h2>Found the following pages that are tagged with "<em><r:search:query/></em>".</h2>
|
32
|
+
|
33
|
+
<ul>
|
34
|
+
<r:search:results:each>
|
35
|
+
<li><r:link/> - <r:author/> - <r:date/></li>
|
36
|
+
</r:search:results:each>
|
37
|
+
</ul>
|
38
|
+
</r:search:results>
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the tags extension.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the tags extension.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'TagsExtension'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
23
|
+
|
24
|
+
# Load any custom rakefiles for extension
|
25
|
+
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class MetaTag < ActiveRecord::Base
|
2
|
+
|
3
|
+
if Radiant::Config['tags.complex_strings'] == 'true'
|
4
|
+
delim = ";"
|
5
|
+
re_format = /^[a-zA-Z0-9,\_\-\s\/()'.&]+$/
|
6
|
+
else
|
7
|
+
delim = " "
|
8
|
+
re_format = /^[a-zA-Z0-9\_\-]+$/
|
9
|
+
end
|
10
|
+
DELIMITER = delim
|
11
|
+
# how to separate tags in strings (you may
|
12
|
+
# also need to change the validates_format_of parameters
|
13
|
+
# if you update this)
|
14
|
+
|
15
|
+
# if speed becomes an issue, you could remove these validations
|
16
|
+
# and rescue the AR index errors instead
|
17
|
+
validates_presence_of :name
|
18
|
+
validates_uniqueness_of :name, :case_sensitive => false
|
19
|
+
validates_format_of :name, :with => re_format,
|
20
|
+
:message => "can not contain special characters"
|
21
|
+
|
22
|
+
has_many_polymorphs :taggables,
|
23
|
+
:from => [:pages],
|
24
|
+
:through => :taggings,
|
25
|
+
:dependent => :destroy,
|
26
|
+
:skip_duplicates => false
|
27
|
+
|
28
|
+
def after_save
|
29
|
+
# if you allow editable tag names, you might want before_save instead
|
30
|
+
self.name = name.downcase.strip.squeeze(" ")
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def find_or_create_by_name!(name)
|
35
|
+
find_by_name(name) || create!(:name => name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def cloud(args = {})
|
39
|
+
find(:all, :select => 'meta_tags.*, count(*) as popularity',
|
40
|
+
:limit => args[:limit] || 5,
|
41
|
+
:joins => "JOIN taggings ON taggings.meta_tag_id = meta_tags.id",
|
42
|
+
:conditions => args[:conditions],
|
43
|
+
:group => "meta_tags.id, meta_tags.name",
|
44
|
+
:order => "popularity DESC" )
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def <=>(other)
|
49
|
+
# To be able to sort an array of tags
|
50
|
+
name <=> other.name
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,328 @@
|
|
1
|
+
module RadiusTags
|
2
|
+
include Radiant::Taggable
|
3
|
+
include ActionView::Helpers::TextHelper
|
4
|
+
|
5
|
+
class TagError < StandardError; end
|
6
|
+
|
7
|
+
desc %{
|
8
|
+
Expands if a <pre><r:tagged with="" /></pre> call would return items. Takes the same options as the 'tagged' tag.
|
9
|
+
The <pre><r:unless_tagged with="" /></pre> is also available.
|
10
|
+
}
|
11
|
+
tag "if_tagged" do |tag|
|
12
|
+
if tag.attr["with"]
|
13
|
+
tag.locals.tagged_results = find_with_tag_options(tag)
|
14
|
+
tag.expand unless tag.locals.tagged_results.empty?
|
15
|
+
else
|
16
|
+
tag.expand unless tag.locals.page.tag_list.empty?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
tag "unless_tagged" do |tag|
|
20
|
+
if tag.attr["with"]
|
21
|
+
tag.expand if find_with_tag_options(tag).empty?
|
22
|
+
else
|
23
|
+
tag.expand if tag.locals.page.tag_list.empty?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc %{
|
28
|
+
Find all pages with certain tags, within in an optional scope. Additionally, you may set with_any to true to select pages that have any of the listed tags (opposed to all listed tags which is the provided default).
|
29
|
+
|
30
|
+
*Usage:*
|
31
|
+
<pre><code><r:tagged with="shoes diesel" [scope="/fashion/cult-update"] [with_any="true"] [offset="number"] [limit="number"] [by="attribute"] [order="asc|desc"]>...</r:tagged></code></pre>
|
32
|
+
}
|
33
|
+
tag "tagged" do |tag|
|
34
|
+
unless tag.locals.tagged_results.nil? # We're inside an r:if_tagged, so results are already available;
|
35
|
+
results = tag.locals.tagged_results
|
36
|
+
else
|
37
|
+
results = find_with_tag_options(tag)
|
38
|
+
end
|
39
|
+
output = []
|
40
|
+
results.each do |page|
|
41
|
+
tag.locals.page = page
|
42
|
+
output << tag.expand
|
43
|
+
end
|
44
|
+
output
|
45
|
+
end
|
46
|
+
|
47
|
+
desc %{
|
48
|
+
Find all pages related to the current page, based on all or any of the current page's tags. A scope attribute may be given to limit results to a certain site area.
|
49
|
+
|
50
|
+
*Usage:*
|
51
|
+
<pre><code><r:related_by_tags [scope="/fashion/cult-update"] [offset="number"] [limit="number"] [by="attribute"] [order="asc|desc"]>...</r:related_by_tags></code></pre>
|
52
|
+
}
|
53
|
+
tag "related_by_tags" do |tag|
|
54
|
+
tag.attr["with"] = tag.locals.page.tag_list.split(MetaTag::DELIMITER)
|
55
|
+
tag.attr["with_any"] = true
|
56
|
+
tag.attr["exclude_id"] = tag.locals.page.id
|
57
|
+
results = find_with_tag_options(tag)
|
58
|
+
return false if results.size < 1
|
59
|
+
output = []
|
60
|
+
first = true
|
61
|
+
results.each do |page|
|
62
|
+
tag.locals.page = page
|
63
|
+
tag.locals.first = first
|
64
|
+
output << tag.expand
|
65
|
+
first = false
|
66
|
+
end
|
67
|
+
output
|
68
|
+
end
|
69
|
+
|
70
|
+
tag "if_has_related_by_tags" do |tag|
|
71
|
+
tag.attr["with"] = tag.locals.page.tag_list.split(MetaTag::DELIMITER)
|
72
|
+
tag.attr["with_any"] = true
|
73
|
+
tag.attr["exclude_id"] = tag.locals.page.id
|
74
|
+
results = find_with_tag_options(tag)
|
75
|
+
results -= [tag.locals.page]
|
76
|
+
tag.expand if results.size > 0
|
77
|
+
end
|
78
|
+
|
79
|
+
tag "related_by_tags:if_first" do |tag|
|
80
|
+
tag.expand if tag.locals.first
|
81
|
+
end
|
82
|
+
|
83
|
+
desc %{
|
84
|
+
Render a Tag cloud
|
85
|
+
The results_page attribute will default to #{Radiant::Config['tags.results_page_url']}
|
86
|
+
|
87
|
+
*Usage:*
|
88
|
+
<pre><code><r:tag_cloud_list [limit="number"] [results_page="/some/url"] [scope="/some/url"]/></code></pre>
|
89
|
+
}
|
90
|
+
tag "tag_cloud" do |tag|
|
91
|
+
tag_cloud = MetaTag.cloud(:limit => tag.attr['limit'] || 5).sort
|
92
|
+
tag_cloud = filter_tags_to_url_scope(tag_cloud, tag.attr['scope']) unless tag.attr['scope'].nil?
|
93
|
+
|
94
|
+
results_page = tag.attr['results_page'] || Radiant::Config['tags.results_page_url']
|
95
|
+
output = "<ol class=\"tag_cloud\">"
|
96
|
+
if tag_cloud.length > 0
|
97
|
+
build_tag_cloud(tag_cloud, %w(size1 size2 size3 size4 size5 size6 size7 size8 size9)) do |tag, cloud_class, amount|
|
98
|
+
output += "<li class=\"#{cloud_class}\"><span>#{pluralize(amount, 'page is', 'pages are')} tagged with </span><a href=\"#{results_page}/#{tag}\" class=\"tag\">#{tag}</a></li>"
|
99
|
+
end
|
100
|
+
else
|
101
|
+
return "<p>No tags found.</p>"
|
102
|
+
end
|
103
|
+
output += "</ol>"
|
104
|
+
end
|
105
|
+
|
106
|
+
desc %{
|
107
|
+
Render a Tag list, more for 'categories'-ish usage, i.e.: Cats (2) Logs (1) ...
|
108
|
+
The results_page attribute will default to #{Radiant::Config['tags.results_page_url']}
|
109
|
+
|
110
|
+
*Usage:*
|
111
|
+
<pre><code><r:tag_cloud_list [results_page="/some/url"] [scope="/some/url"]/></code></pre>
|
112
|
+
}
|
113
|
+
tag "tag_cloud_list" do |tag|
|
114
|
+
tag_cloud = MetaTag.cloud({:limit => 100}).sort
|
115
|
+
tag_cloud = filter_tags_to_url_scope(tag_cloud, tag.attr['scope']) unless tag.attr['scope'].nil?
|
116
|
+
|
117
|
+
results_page = tag.attr['results_page'] || Radiant::Config['tags.results_page_url']
|
118
|
+
output = "<ul class=\"tag_list\">"
|
119
|
+
if tag_cloud.length > 0
|
120
|
+
build_tag_cloud(tag_cloud, %w(size1 size2 size3 size4 size5 size6 size7 size8 size9)) do |tag, cloud_class, amount|
|
121
|
+
output += "<li class=\"#{cloud_class}\"><a href=\"#{results_page}/#{tag}\" class=\"tag\">#{tag} (#{amount})</a></li>"
|
122
|
+
end
|
123
|
+
else
|
124
|
+
return "<p>No tags found.</p>"
|
125
|
+
end
|
126
|
+
output += "</ul>"
|
127
|
+
end
|
128
|
+
|
129
|
+
desc "List the current page's tags"
|
130
|
+
tag "tag_list" do |tag|
|
131
|
+
results_page = tag.attr['results_page'] || Radiant::Config['tags.results_page_url']
|
132
|
+
output = []
|
133
|
+
tag.locals.page.tag_list.split(MetaTag::DELIMITER).each {|t| output << "<a href=\"#{results_page}/#{t}\" class=\"tag\">#{t}</a>"}
|
134
|
+
output.join ", "
|
135
|
+
end
|
136
|
+
|
137
|
+
desc "List the current page's tagsi as technorati tags. this should be included in the body of a post or in your rss feed"
|
138
|
+
tag "tag_list_technorati" do |tag|
|
139
|
+
output = []
|
140
|
+
tag.locals.page.tag_list.split(MetaTag::DELIMITER).each {|t| output << "<a href=\"http://technorati.com/tag/#{ t.split(" ").join("+")}\" rel=\"tag\">#{t}</a>"}
|
141
|
+
output.join ", "
|
142
|
+
end
|
143
|
+
|
144
|
+
tag "tags" do |tag|
|
145
|
+
tag.expand
|
146
|
+
end
|
147
|
+
|
148
|
+
desc "Iterates over the tags of the current page"
|
149
|
+
tag "tags:each" do |tag|
|
150
|
+
result = []
|
151
|
+
tag.locals.page.meta_tags.each do |meta_tag|
|
152
|
+
tag.locals.meta_tag = meta_tag
|
153
|
+
result << tag.expand
|
154
|
+
end
|
155
|
+
result
|
156
|
+
end
|
157
|
+
|
158
|
+
tag "tags:each:name" do |tag|
|
159
|
+
tag.locals.meta_tag.name
|
160
|
+
end
|
161
|
+
|
162
|
+
tag "tags:each:link" do |tag|
|
163
|
+
results_page = tag.attr['results_page'] || Radiant::Config['tags.results_page_url']
|
164
|
+
name = tag.locals.meta_tag.name
|
165
|
+
return "<a href=\"#{results_page}/#{name}\" class=\"tag\">#{name}</a>"
|
166
|
+
end
|
167
|
+
|
168
|
+
desc "Set the scope for all tags in the database"
|
169
|
+
tag "all_tags" do |tag|
|
170
|
+
tag.expand
|
171
|
+
end
|
172
|
+
|
173
|
+
desc %{
|
174
|
+
Iterates through each tag and allows you to specify the order: by popularity or by name.
|
175
|
+
The default is by name. You may also limit the search; the default is 5 results.
|
176
|
+
|
177
|
+
Usage: <pre><code><r:all_tags:each order="popularity" limit="5">...</r:all_tags:each></code></pre>
|
178
|
+
}
|
179
|
+
tag "all_tags:each" do |tag|
|
180
|
+
order = tag.attr['order'] || 'name'
|
181
|
+
limit = tag.attr['limit'] || '5'
|
182
|
+
result = []
|
183
|
+
case order
|
184
|
+
when 'name'
|
185
|
+
all_tags = MetaTag.find(:all, :limit => limit)
|
186
|
+
else
|
187
|
+
all_tags = MetaTag.cloud(:limit => limit)
|
188
|
+
end
|
189
|
+
all_tags.each do |t|
|
190
|
+
next if t.pages.empty? # skip unused tags
|
191
|
+
tag.locals.meta_tag = t
|
192
|
+
result << tag.expand
|
193
|
+
end
|
194
|
+
result
|
195
|
+
end
|
196
|
+
|
197
|
+
desc "Renders the tag's name"
|
198
|
+
tag "all_tags:each:name" do |tag|
|
199
|
+
tag.locals.meta_tag.name
|
200
|
+
end
|
201
|
+
|
202
|
+
tag "all_tags:each:link" do |tag|
|
203
|
+
results_page = tag.attr['results_page'] || Radiant::Config['tags.results_page_url']
|
204
|
+
name = tag.locals.meta_tag.name
|
205
|
+
return "<a href=\"#{results_page}/#{name}\" class=\"tag\">#{name}</a>"
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
desc "Set the scope for the tag's pages"
|
210
|
+
tag "all_tags:each:pages" do |tag|
|
211
|
+
tag.expand
|
212
|
+
end
|
213
|
+
|
214
|
+
desc "Iterates through each page"
|
215
|
+
tag "all_tags:each:pages:each" do |tag|
|
216
|
+
result = []
|
217
|
+
tag.locals.meta_tag.taggables.each do |taggable|
|
218
|
+
if taggable.is_a?(Page)
|
219
|
+
tag.locals.page = taggable
|
220
|
+
result << tag.expand
|
221
|
+
end
|
222
|
+
end
|
223
|
+
result
|
224
|
+
end
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
def build_tag_cloud(tag_cloud, style_list)
|
229
|
+
max, min = 0, 0
|
230
|
+
tag_cloud.each do |tag|
|
231
|
+
max = tag.popularity.to_i if tag.popularity.to_i > max
|
232
|
+
min = tag.popularity.to_i if tag.popularity.to_i < min
|
233
|
+
end
|
234
|
+
|
235
|
+
divisor = ((max - min) / style_list.size) + 1
|
236
|
+
|
237
|
+
tag_cloud.each do |tag|
|
238
|
+
yield tag.name, style_list[(tag.popularity.to_i - min) / divisor], tag.popularity.to_i
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def tag_item_url(name)
|
243
|
+
"#{Radiant::Config['tags.results_page_url']}/#{name}"
|
244
|
+
end
|
245
|
+
|
246
|
+
def find_with_tag_options(tag)
|
247
|
+
options = tagged_with_options(tag)
|
248
|
+
with_any = tag.attr['with_any'] || false
|
249
|
+
scope_attr = tag.attr['scope'] || '/'
|
250
|
+
results = []
|
251
|
+
raise TagError, "`tagged' tag must contain a `with' attribute." unless (tag.attr['with'] || tag.locals.page.class_name = TagSearchPage)
|
252
|
+
ttag = tag.attr['with'] || @request.parameters[:tag]
|
253
|
+
|
254
|
+
scope = scope_attr == 'current_page' ? Page.find_by_url(@request.request_uri) : Page.find_by_url(scope_attr)
|
255
|
+
return "The scope attribute must be a valid url to an existing page." if scope.nil? || scope.class_name.eql?('FileNotFoundPage')
|
256
|
+
|
257
|
+
if with_any
|
258
|
+
Page.tagged_with_any(ttag, options).each do |page|
|
259
|
+
next unless (page.ancestors.include?(scope) or page == scope)
|
260
|
+
results << page
|
261
|
+
end
|
262
|
+
else
|
263
|
+
Page.tagged_with(ttag, options).each do |page|
|
264
|
+
next unless (page.ancestors.include?(scope) or page == scope)
|
265
|
+
results << page
|
266
|
+
end
|
267
|
+
end
|
268
|
+
results
|
269
|
+
end
|
270
|
+
|
271
|
+
def tagged_with_options(tag)
|
272
|
+
attr = tag.attr.symbolize_keys
|
273
|
+
|
274
|
+
options = {}
|
275
|
+
|
276
|
+
[:limit, :offset].each do |symbol|
|
277
|
+
if number = attr[symbol]
|
278
|
+
if number =~ /^\d{1,4}$/
|
279
|
+
options[symbol] = number.to_i
|
280
|
+
else
|
281
|
+
raise TagError.new("`#{symbol}' attribute of `each' tag must be a positive number between 1 and 4 digits")
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
by = (attr[:by] || 'published_at').strip
|
287
|
+
order = (attr[:order] || 'asc').strip
|
288
|
+
order_string = ''
|
289
|
+
if self.attributes.keys.include?(by)
|
290
|
+
order_string << by
|
291
|
+
else
|
292
|
+
raise TagError.new("`by' attribute of `each' tag must be set to a valid field name")
|
293
|
+
end
|
294
|
+
if order =~ /^(asc|desc)$/i
|
295
|
+
order_string << " #{$1.upcase}"
|
296
|
+
else
|
297
|
+
raise TagError.new(%{`order' attribute of `each' tag must be set to either "asc" or "desc"})
|
298
|
+
end
|
299
|
+
options[:order] = order_string
|
300
|
+
|
301
|
+
status = (attr[:status] || 'published').downcase
|
302
|
+
exclude = attr[:exclude_id] ? "AND pages.id != #{attr[:exclude_id]}" : ""
|
303
|
+
|
304
|
+
unless status == 'all'
|
305
|
+
stat = Status[status]
|
306
|
+
unless stat.nil?
|
307
|
+
options[:conditions] = ["(virtual = ?) and (status_id = ?) #{exclude} and (published_at <= ?)", false, stat.id, Time.current]
|
308
|
+
else
|
309
|
+
raise TagError.new(%{`status' attribute of `each' tag must be set to a valid status})
|
310
|
+
end
|
311
|
+
else
|
312
|
+
options[:conditions] = ["virtual = ? #{exclude}", false]
|
313
|
+
end
|
314
|
+
options
|
315
|
+
end
|
316
|
+
|
317
|
+
def filter_tags_to_url_scope(tags, scope)
|
318
|
+
new_tags = []
|
319
|
+
tags.each do |t|
|
320
|
+
catch :record_found do # using fancy ballsports stuff to avoid unnecessary db calls (by calling each page, ànd by calling page.url)
|
321
|
+
t.pages.each do |p|
|
322
|
+
(new_tags << t; throw :record_found) if p.url.include?(scope)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
new_tags
|
327
|
+
end
|
328
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
class TagSearchPage < Page
|
2
|
+
|
3
|
+
attr_accessor :requested_tag
|
4
|
+
#### Tags ####
|
5
|
+
desc %{ The namespace for all search tags.}
|
6
|
+
tag 'search' do |tag|
|
7
|
+
tag.expand
|
8
|
+
end
|
9
|
+
|
10
|
+
desc %{ Renders the passed query.}
|
11
|
+
tag 'search:query' do |tag|
|
12
|
+
CGI.escapeHTML(requested_tag)
|
13
|
+
end
|
14
|
+
|
15
|
+
desc %{ Renders the contained block if no results were returned.}
|
16
|
+
tag 'search:empty' do |tag|
|
17
|
+
if found_tags.blank?
|
18
|
+
tag.expand
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc %{ Renders the contained block if results were returned.}
|
23
|
+
tag 'search:results' do |tag|
|
24
|
+
unless found_tags.blank?
|
25
|
+
tag.expand
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc %{ <r:search:results:each [sort_by="id"] [order="asc"]/>
|
30
|
+
Renders the contained block for each result page. The context
|
31
|
+
inside the tag refers to the found page. The optional sort_by and order attributes
|
32
|
+
specify how the results are sorted}
|
33
|
+
tag 'search:results:each' do |tag|
|
34
|
+
# Ordering in Ruby because we already fetched our resultset before
|
35
|
+
tags = found_tags
|
36
|
+
tags = tags.sort_by(&tag.attr['sort_by'].to_sym) if tag.attr['sort_by']
|
37
|
+
tags = tags.reverse if tag.attr['order'].to_s =~ /desc/i
|
38
|
+
|
39
|
+
returning String.new do |content|
|
40
|
+
tags.each do |page|
|
41
|
+
tag.locals.page = page
|
42
|
+
content << tag.expand
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
desc %{ <r:truncate_and_strip [length="100"] />
|
48
|
+
Truncates and strips all HTML tags from the content of the contained block.
|
49
|
+
Useful for displaying a snippet of a found page. The optional `length' attribute
|
50
|
+
specifies how many characters to truncate to.}
|
51
|
+
tag 'truncate_and_strip' do |tag|
|
52
|
+
tag.attr['length'] ||= 100
|
53
|
+
length = tag.attr['length'].to_i
|
54
|
+
helper = ActionView::Base.new
|
55
|
+
helper.truncate(helper.strip_tags(tag.expand).gsub(/\s+/," "), length)
|
56
|
+
end
|
57
|
+
|
58
|
+
#### "Behavior" methods ####
|
59
|
+
def cache?
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
def found_tags
|
64
|
+
return @found_tags if @found_tags
|
65
|
+
return [] if requested_tag.blank?
|
66
|
+
|
67
|
+
@found_tags = Page.tagged_with(requested_tag).delete_if { |p| !p.published? }
|
68
|
+
end
|
69
|
+
|
70
|
+
def render
|
71
|
+
self.requested_tag = @request.parameters[:tag] unless requested_tag
|
72
|
+
self.title = "Tagged with #{requested_tag}" if requested_tag
|
73
|
+
|
74
|
+
super
|
75
|
+
end
|
76
|
+
|
77
|
+
def find_by_url(url, live = true, clean = false)
|
78
|
+
url = clean_url(url).chop # chop off trailing slash added by clean_url
|
79
|
+
if url =~ /^#{self.url}([a-zA-Z0-9,\_\-\s\/()'.&]*)\/?$/
|
80
|
+
self.requested_tag = $1
|
81
|
+
self
|
82
|
+
else
|
83
|
+
super
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Tagging < ActiveRecord::Base
|
2
|
+
belongs_to :meta_tag
|
3
|
+
belongs_to :taggable, :polymorphic => true
|
4
|
+
|
5
|
+
def before_destroy
|
6
|
+
# if all the taggings for a particular <%= parent_association_name -%> are deleted, we want to
|
7
|
+
# delete the <%= parent_association_name -%> too
|
8
|
+
meta_tag.destroy_without_callbacks if meta_tag.taggings.count < 2
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
%h4 Tags
|
2
|
+
%p Tags that you list on your pages are ad-hoc categories and tags that you apply to your pages are as flexible as you want them to be. Rather than selecting a category for your page from a pre-defined list of categories, you can create whatever you need.
|
3
|
+
%p Tags are delimited (separated) by a space, so if you want to tag a page with Totally Awesome as one tag, be sure to put it in quotes such as 'Totally Awesome', otherwise you'll create two tags: one called Totally and one called Awesome.
|
4
|
+
%p These tags may be used by the site developers to provide a list of links (for example) to a group of pages with the same tag.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class AddTagSupport < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :meta_tags do |t|
|
4
|
+
t.column :name, :string, :null => false
|
5
|
+
end
|
6
|
+
add_index :meta_tags, :name, :unique => true
|
7
|
+
|
8
|
+
create_table :taggings do |t|
|
9
|
+
t.column :meta_tag_id, :integer, :null => false
|
10
|
+
t.column :taggable_id, :integer, :null => false
|
11
|
+
t.column :taggable_type, :string, :null => false
|
12
|
+
end
|
13
|
+
add_index :taggings, [:meta_tag_id, :taggable_id, :taggable_type], :unique => true
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.down
|
17
|
+
drop_table :meta_tags
|
18
|
+
drop_table :taggings
|
19
|
+
end
|
20
|
+
end
|