infopark_rails_connector 6.9.1.3.22208381 → 6.9.2.1.125136549

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. data/README +2 -14
  2. data/app/assets/javascripts/infopark_rails_connector.js.erb +0 -3
  3. data/app/assets/stylesheets/infopark_rails_connector.css.erb +0 -4
  4. data/app/controllers/rails_connector/default_cms_controller.rb +0 -1
  5. data/app/helpers/rails_connector/default_cms_helper.rb +0 -6
  6. data/app/helpers/rails_connector/layout_helper.rb +2 -7
  7. data/app/views/cms/index.html.erb +0 -2
  8. data/app/views/errors/410_gone.html.erb +2 -2
  9. data/config/ca-bundle.crt +1 -1
  10. data/config/cms_routes.rb +2 -1
  11. data/config/locales/de.rails_connector.views.yml +0 -78
  12. data/config/locales/en.rails_connector.views.yml +0 -78
  13. data/lib/generators/rails_connector/install/install_generator.rb +0 -1
  14. data/lib/generators/rails_connector/install/templates/initializers/rails_connector.rb +0 -27
  15. data/lib/rails_connector/cms_accessible.rb +0 -4
  16. data/lib/rails_connector/configuration.rb +9 -72
  17. data/lib/rails_connector/engine.rb +0 -18
  18. metadata +3 -181
  19. data/app/assets/images/ratings/star.gif +0 -0
  20. data/app/assets/images/time_machine/calendar-menuarrow.gif +0 -0
  21. data/app/assets/images/time_machine/calendar_bg.png +0 -0
  22. data/app/assets/images/time_machine/icon.png +0 -0
  23. data/app/assets/images/time_machine/slider_bg.png +0 -0
  24. data/app/assets/images/time_machine/slider_handle.png +0 -0
  25. data/app/assets/images/time_machine/timemachine_bg.png +0 -0
  26. data/app/assets/javascripts/comments.js +0 -29
  27. data/app/assets/javascripts/initializer.js +0 -9
  28. data/app/assets/javascripts/ratings.js +0 -26
  29. data/app/assets/javascripts/time_machine.js +0 -8
  30. data/app/assets/javascripts/time_machine/calendar-setup.js +0 -200
  31. data/app/assets/javascripts/time_machine/calendar.js +0 -1806
  32. data/app/assets/javascripts/time_machine/lang/calendar-de.js +0 -127
  33. data/app/assets/javascripts/time_machine/lang/calendar-en.js +0 -127
  34. data/app/assets/javascripts/time_machine/lang/calendar-es.js +0 -129
  35. data/app/assets/javascripts/time_machine/lang/calendar-fr.js +0 -125
  36. data/app/assets/javascripts/time_machine/lang/calendar-it.js +0 -124
  37. data/app/assets/javascripts/time_machine/slider.js +0 -278
  38. data/app/assets/stylesheets/ratings.css +0 -97
  39. data/app/assets/stylesheets/time_machine.css +0 -6
  40. data/app/assets/stylesheets/time_machine/time_machine.css +0 -292
  41. data/app/controllers/comments_controller.rb +0 -6
  42. data/app/controllers/crm_form_controller.rb +0 -6
  43. data/app/controllers/rails_connector/default_comments_controller.rb +0 -70
  44. data/app/controllers/rails_connector/default_crm_form_controller.rb +0 -167
  45. data/app/controllers/rails_connector/default_ratings_controller.rb +0 -84
  46. data/app/controllers/rails_connector/default_rss_controller.rb +0 -30
  47. data/app/controllers/rails_connector/default_search_controller.rb +0 -60
  48. data/app/controllers/rails_connector/default_user_controller.rb +0 -269
  49. data/app/controllers/rails_connector/time_machine_controller.rb +0 -48
  50. data/app/controllers/ratings_controller.rb +0 -6
  51. data/app/controllers/rss_controller.rb +0 -6
  52. data/app/controllers/search_controller.rb +0 -6
  53. data/app/controllers/seo_sitemap_controller.rb +0 -12
  54. data/app/controllers/user_controller.rb +0 -6
  55. data/app/helpers/crm_form_helper.rb +0 -6
  56. data/app/helpers/rails_connector/default_crm_form_helper.rb +0 -58
  57. data/app/helpers/rails_connector/default_ratings_helper.rb +0 -38
  58. data/app/helpers/rails_connector/default_user_helper.rb +0 -90
  59. data/app/helpers/rails_connector/error_messages_helper.rb +0 -23
  60. data/app/helpers/rails_connector/link_helper.rb +0 -93
  61. data/app/helpers/rails_connector/mandatory_label_helper.rb +0 -10
  62. data/app/helpers/rails_connector/menu_helper.rb +0 -73
  63. data/app/helpers/rails_connector/micronav_helper.rb +0 -109
  64. data/app/helpers/rails_connector/seo_helper.rb +0 -44
  65. data/app/helpers/rails_connector/time_machine_helper.rb +0 -26
  66. data/app/helpers/rails_connector/tracking_helper.rb +0 -32
  67. data/app/helpers/ratings_helper.rb +0 -4
  68. data/app/helpers/user_helper.rb +0 -6
  69. data/app/mailers/confirmation_mailer.rb +0 -15
  70. data/app/models/crm_form.rb +0 -2
  71. data/app/models/rails_connector/default_comment.rb +0 -30
  72. data/app/models/rails_connector/default_rating.rb +0 -22
  73. data/app/views/cms/_comments.html.erb +0 -44
  74. data/app/views/cms/_rating.html.erb +0 -31
  75. data/app/views/comments/_comment.html.erb +0 -28
  76. data/app/views/confirmation_mailer/register_confirmation.erb +0 -5
  77. data/app/views/confirmation_mailer/reset_password.erb +0 -5
  78. data/app/views/crm_form/_flash_messages.html.erb +0 -11
  79. data/app/views/crm_form/_form.html.erb +0 -17
  80. data/app/views/crm_form/confirmation.html.erb +0 -3
  81. data/app/views/crm_form/index.html.erb +0 -5
  82. data/app/views/crm_form/not_logged_in.html.erb +0 -1
  83. data/app/views/layouts/rails_connector/time_machine.html.erb +0 -12
  84. data/app/views/rails_connector/time_machine/index.html.erb +0 -88
  85. data/app/views/rss/_item.rss.builder +0 -11
  86. data/app/views/rss/index.rss.builder +0 -11
  87. data/app/views/search/_hit.html.erb +0 -11
  88. data/app/views/search/_hits.html.erb +0 -11
  89. data/app/views/search/_mini_panel.html.erb +0 -4
  90. data/app/views/search/_pagination.html.erb +0 -5
  91. data/app/views/search/_panel.html.erb +0 -4
  92. data/app/views/search/search.html.erb +0 -12
  93. data/app/views/seo_sitemap/show.xml.builder +0 -16
  94. data/app/views/user/_flash_messages.html.erb +0 -11
  95. data/app/views/user/edit.html.erb +0 -6
  96. data/app/views/user/edit_password.html.erb +0 -11
  97. data/app/views/user/forgot_password.html.erb +0 -7
  98. data/app/views/user/login.html.erb +0 -15
  99. data/app/views/user/new.html.erb +0 -13
  100. data/app/views/user/profile.html.erb +0 -8
  101. data/app/views/user/register_pending.html.erb +0 -1
  102. data/app/views/user/set_password.html.erb +0 -14
  103. data/config/locales/de.rails_connector.controllers.yml +0 -28
  104. data/config/locales/de.rails_connector.helpers.yml +0 -9
  105. data/config/locales/de.rails_connector.models.yml +0 -8
  106. data/config/locales/en.rails_connector.controllers.yml +0 -28
  107. data/config/locales/en.rails_connector.helpers.yml +0 -9
  108. data/config/locales/en.rails_connector.models.yml +0 -8
  109. data/config/routes.rb +0 -31
  110. data/lib/generators/rails_connector/comments/comments_generator.rb +0 -20
  111. data/lib/generators/rails_connector/comments/templates/migration.rb +0 -16
  112. data/lib/generators/rails_connector/install/templates/initializers/crm_connector.rb +0 -22
  113. data/lib/generators/rails_connector/ratings/ratings_generator.rb +0 -20
  114. data/lib/generators/rails_connector/ratings/templates/migration.rb +0 -14
  115. data/lib/rails_connector/commentable.rb +0 -23
  116. data/lib/rails_connector/configuration/google_analytics.rb +0 -29
  117. data/lib/rails_connector/configuration/rss.rb +0 -46
  118. data/lib/rails_connector/crm.rb +0 -282
  119. data/lib/rails_connector/googlebot_checker.rb +0 -46
  120. data/lib/rails_connector/liquid_support.rb +0 -25
  121. data/lib/rails_connector/liquid_support/field_value_drop.rb +0 -22
  122. data/lib/rails_connector/liquid_support/general_helper_tag.rb +0 -44
  123. data/lib/rails_connector/liquid_support/link_drop.rb +0 -22
  124. data/lib/rails_connector/liquid_support/liquid_template_handler.rb +0 -162
  125. data/lib/rails_connector/liquid_support/named_object_drop.rb +0 -14
  126. data/lib/rails_connector/liquid_support/obj_drop.rb +0 -43
  127. data/lib/rails_connector/liquid_support/obj_filters.rb +0 -77
  128. data/lib/rails_connector/rateable.rb +0 -57
  129. data/lib/rails_connector/seo.rb +0 -52
  130. data/lib/rails_connector/ses.rb +0 -81
  131. data/lib/rails_connector/syndicateable.rb +0 -11
  132. data/lib/search_request.rb +0 -2
@@ -1,44 +0,0 @@
1
- module RailsConnector::LiquidSupport
2
-
3
- # This is a wrapper class used internally to make helper methods available in
4
- # Liquid templates. Helpers have to be enabled in the app initialization like this:
5
- #
6
- # RailsConnector::LiquidSupport.enable_helpers(
7
- # :helper_a,
8
- # :helper_b
9
- # )
10
- class GeneralHelperTag < Liquid::Tag
11
- attr_reader :params
12
-
13
- def initialize(tag_name, markup, tokens)
14
- @tag_name = tag_name
15
- @params = markup.to_s.scan(/(#{::Liquid::Expression})*/).flatten.compact.map(&:strip)
16
- super
17
- end
18
-
19
- def render(context)
20
- context.registers[:action_view].__send__(@tag_name, *params(context))
21
- end
22
-
23
- def self.<<(helper)
24
- Liquid::Template.register_tag(helper, self)
25
- self
26
- end
27
-
28
- protected
29
-
30
- def params(context)
31
- @params.map { |p| context[p] || p }.map do |item|
32
- case item
33
- when LinkDrop
34
- item.destination.__drop_content
35
- when ObjDrop
36
- item.__drop_content
37
- else
38
- item.to_s
39
- end
40
- end
41
- end
42
- end
43
-
44
- end
@@ -1,22 +0,0 @@
1
- module RailsConnector::LiquidSupport
2
-
3
- # Dieser Drop kapselt einen Link.
4
- class LinkDrop < Liquid::Drop
5
- def initialize(link)
6
- @link = link
7
- end
8
-
9
- def __drop_content
10
- @link
11
- end
12
-
13
- [:url, :external?, :internal?, :title, :display_title].each do |m|
14
- define_method(m) { @link.__send__(m).to_liquid }
15
- end
16
-
17
- def destination
18
- @link.destination_object.to_liquid
19
- end
20
- end
21
-
22
- end
@@ -1,162 +0,0 @@
1
- module RailsConnector::LiquidSupport
2
-
3
- module FieldValueDropPatcher
4
- def self.patch(mod)
5
- mod.module_eval do
6
- return if method_defined?(:field_value_drop_patched)
7
- define_method :field_value_drop_patched do; end
8
- (public_instance_methods - Module.public_instance_methods).each do |m|
9
- alias_method(old_m = "infopark_rails_connector_%s" % m, m)
10
- define_method m do |*args|
11
- first_arg = args.shift
12
- args.map!{|arg| arg.kind_of?(FieldValueDrop) ? arg.__value : arg}
13
- args.unshift(first_arg)
14
- if (drop = args.first).kind_of? FieldValueDrop
15
- args[0] = drop.__value
16
- value = __send__(old_m, *args)
17
- new_drop = drop.dup
18
- new_drop.__value = value
19
- return new_drop
20
- else
21
- return __send__(old_m, *args)
22
- end
23
- end
24
- end
25
- end
26
- end
27
- end
28
-
29
- FieldValueDropPatcher.patch(Liquid::StandardFilters)
30
-
31
- # A tag for rendering partials in Liquid templates
32
- #
33
- # Example:
34
- # {% template 'name-of-partial' %}
35
- class TemplateTag < Liquid::Tag
36
- Syntax = /(#{Liquid::QuotedFragment}+)/
37
-
38
- def initialize(tag_name, markup, tokens)
39
-
40
- if markup =~ Syntax
41
- @partial_name = $1
42
- else
43
- raise Liquid::SyntaxError.new("Error in tag 'template' - Valid syntax: template '[name-of-template]'")
44
- end
45
-
46
- super
47
- end
48
-
49
- def render(context)
50
- context.registers[:action_view].controller.__send__(
51
- :render_to_string, :partial => context[@partial_name]
52
- )
53
- end
54
-
55
- Liquid::Template.register_tag('template', TemplateTag)
56
- end
57
-
58
- # Das LiquidTemplateRepository kann Liquid-Templates anwenden.
59
- # Zunächst muss das Template kompiliert werden, danach kann es gerendert werden.
60
- class LiquidTemplateRepository
61
-
62
- cattr_accessor :compiled_templates
63
- self.compiled_templates = {}
64
-
65
- def self.compile(template)
66
- template_id = generate_unique_template_id
67
- compiled_templates[template_id] = Liquid::Template.parse(template.source)
68
- template_id
69
- end
70
-
71
- def self.render(template_id, action_view)
72
- compiled_template = compiled_templates[template_id]
73
-
74
- unless compiled_template
75
- # this should never happen
76
- raise "render() called with illegal template id: #{template_id}"
77
- end
78
-
79
- rendered_template = compiled_template.render(
80
- {
81
- "obj" => action_view.instance_variable_get("@obj"),
82
- "named_object" => NamedObjectDrop.instance
83
- },
84
- :filters => [ObjFilters] + load_custom_filters,
85
- :registers => {:action_view => action_view}
86
- )
87
-
88
- report_errors(compiled_template, action_view.logger) unless compiled_template.errors.blank?
89
-
90
- rendered_template
91
- end
92
-
93
- # Nur zum Testen gedacht
94
- def self.drop_all
95
- self.compiled_templates = {}
96
- end
97
-
98
- def self.load_custom_filters
99
- return @loaded_custom_filters if @loaded_custom_filters
100
- extract = /^#{Regexp.quote(filters_dir.to_s)}\/?(.*_filters).rb$/
101
- @loaded_custom_filters = Dir["#{filters_dir}/**/*_filters.rb"].map do |file|
102
- filename = file.sub extract, '\1'
103
- require File.join(filters_dir, filename)
104
- filename.camelcase.constantize
105
- end
106
- @loaded_custom_filters.each {|m| FieldValueDropPatcher.patch(m)}
107
- @loaded_custom_filters
108
- end
109
-
110
- # Nur zum Testen gedacht
111
- def self.reset_custom_filters
112
- @loaded_custom_filters = nil
113
- end
114
-
115
- class << self
116
-
117
- private
118
-
119
- def generate_unique_template_id
120
- @template_id_counter ||= 0
121
- @template_id_counter += 1
122
- # include object_id to generate different id's if this class is reloaded by accident
123
- # (which should never happen, but you never know)
124
- "#{object_id}-#{@template_id_counter}"
125
- end
126
-
127
- def report_errors(compiled_template, logger)
128
- if ::RailsConnector::LiquidSupport.raise_template_errors
129
- raise compiled_template.errors.first
130
- else
131
- logger.warn(
132
- compiled_template.errors.map do |exception|
133
- "[Liquid Error] #{exception.message} trace: \n#{exception.backtrace.join("\n")}"
134
- end.join("\n\n")
135
- )
136
- end
137
- end
138
-
139
- def filters_dir
140
- Rails.root.join('app', 'filters')
141
- end
142
-
143
- end
144
-
145
- end
146
-
147
- # Dieser TemplateHandler integriert Liquid in Rails.
148
- #
149
- # Die Klasse ist bewusst sehr schlank gehalten und delegiert das eigentliche
150
- # Verarbeiten der Templates an das LiquidTemplateRepository.
151
- # Der Grund ist, dass die Klassen, die in Rails als TemplateHandler registriert
152
- # sind von Rails eingefroren werden (mittels Object.freeze) und daher keine
153
- # Klassenvariablen haben können.
154
- class LiquidTemplateHandler
155
- def self.call(template)
156
- template_id = LiquidTemplateRepository.compile(template)
157
- "#{LiquidTemplateRepository}.render('#{template_id}', self)"
158
- end
159
-
160
- end
161
-
162
- end
@@ -1,14 +0,0 @@
1
- require "singleton"
2
-
3
- module RailsConnector::LiquidSupport
4
-
5
- # Dieser Drop realisiert den Zugriff auf Objekte, die per NamedLink referenziert werden
6
- class NamedObjectDrop < Liquid::Drop
7
- include Singleton
8
-
9
- def before_method(method)
10
- RailsConnector::NamedLink.get_object(method)
11
- end
12
-
13
- end
14
- end
@@ -1,43 +0,0 @@
1
- module RailsConnector::LiquidSupport
2
-
3
- # Dieser Drop kapselt ein Obj. Der Zugriff auf das Obj ist nur für [] und ausgewählte Methoden erlaubt.
4
- class ObjDrop < Liquid::Drop
5
- def initialize(obj)
6
- @obj = obj
7
- end
8
-
9
- def __drop_content
10
- @obj
11
- end
12
-
13
- def before_method(method)
14
- raw_value = @obj[method]
15
- if raw_value
16
- value = if raw_value.kind_of?(Time)
17
- raw_value
18
- else
19
- @context.registers[:action_view].display_value(raw_value)
20
- end
21
- if value.kind_of?(::RailsConnector::LinkList)
22
- value
23
- else
24
- FieldValueDrop.new(@obj, method, value, use_edit_markers?)
25
- end
26
- else
27
- @obj.__send__(method) if @obj.respond_to?(method)
28
- end
29
- end
30
-
31
- private
32
-
33
- def use_edit_markers?
34
- if RailsConnector::Configuration.auto_liquid_editmarkers.nil?
35
- true
36
- else
37
- RailsConnector::Configuration.auto_liquid_editmarkers
38
- end
39
- end
40
-
41
- end
42
-
43
- end
@@ -1,77 +0,0 @@
1
- module RailsConnector::LiquidSupport
2
-
3
- # Filters in general are methods used in Liquid templates.
4
- # ObjFilters are filters specifically for dealing with CMS objects.
5
- module ObjFilters
6
-
7
- # Generates a link for the +target+.
8
- # +target+ can be an Obj, a Link or a Linklist.
9
- # If +target+ is a Linklist, the first element of the list will be used.
10
- #
11
- # Example:
12
- # {{ "Click me" | link_to: obj }}
13
- #
14
- def link_to(a, b = nil)
15
- if b
16
- title = a || ""
17
- target = b
18
- else
19
- target = a
20
- end
21
- target = first_link_if_linklist(target)
22
- if target
23
- action_view.link_to(title || target.display_title, drop_cms_path(target))
24
- end
25
- end
26
-
27
- # Generates an IMG tag for +target+.
28
- # +target+ can be an Obj, a Link or a Linklist.
29
- # If +target+ is a Linklist, the first element of the list will be used.
30
- #
31
- # Example:
32
- # {{ @obj | image_tag }}
33
- def image_tag(target, title = nil)
34
- action_view.cms_image_tag(unwrap_drop(target), :alt => title)
35
- end
36
-
37
- # Generates the URL where +target+ can be reached.
38
- # +target+ can be an Obj, a Link or a Linklist.
39
- # If +target+ is a Linklist, the first element of the list will be used.
40
- #
41
- # Example:
42
- # This document can be found at {{ obj | url }}
43
- def url(target)
44
- target = first_link_if_linklist(target)
45
- drop_cms_path(target) if target
46
- end
47
-
48
- # Generates an editmarker for +field_value_drop+
49
- def editmarker(field_value_drop, visible=true)
50
- drop = field_value_drop.dup
51
- drop.__marker = visible
52
- drop
53
- end
54
-
55
- private
56
-
57
- def drop_cms_path(possible_drop)
58
- action_view.cms_path(unwrap_drop(possible_drop))
59
- end
60
-
61
- def unwrap_drop(possible_drop)
62
- possible_drop.respond_to?(:__drop_content) ? possible_drop.__drop_content : possible_drop
63
- end
64
-
65
- def action_view
66
- @context.registers[:action_view]
67
- end
68
-
69
- def first_link_if_linklist(target)
70
- return target if target.is_a?(LinkDrop) || target.is_a?(ObjDrop)
71
- if target.respond_to?(:first)
72
- first_element = target.first.to_liquid
73
- return first_element if first_element.is_a?(LinkDrop)
74
- end
75
- end
76
- end
77
- end
@@ -1,57 +0,0 @@
1
- module RailsConnector
2
- #
3
- # This module provides a mixin for the CMS object model. It provides a {ratings} association and well as several helper methods.
4
- module Rateable
5
-
6
- # returns all Ratings for this Obj.
7
- def ratings
8
- Rating.where(:obj_id => id)
9
- end
10
-
11
- # Creates/updates the rating for a CMS object.
12
- def rate(score)
13
- rating = ratings.find_by_score(score) || ratings.build(:score => score)
14
- rating.count += 1
15
- rating.save
16
- end
17
-
18
- # Returns a count for the particular score for a CMS object.
19
- def count_for_score(score)
20
- rating = ratings.find_by_score(score)
21
- rating ? rating.count : 0
22
- end
23
-
24
- # Determines if a CMS object has already been rated.
25
- def rated?
26
- !ratings.empty?
27
- end
28
-
29
- # Calculates the average rating for a CMS object.
30
- def average_rating
31
- raise TypeError unless rated?
32
- sum, count = ratings.inject([0, 0]) do |(sum, count), rating|
33
- [sum + rating.score * rating.count, count + rating.count]
34
- end
35
- sum.to_f / count.to_f
36
- end
37
-
38
- # Calculates the average rating for a CMS object in per cent.
39
- def average_rating_in_percent
40
- if rated?
41
- (100 * average_rating / Rating::MAXIMUM).to_i
42
- else
43
- 0
44
- end
45
- end
46
-
47
- # Resets the ratings for a CMS object.
48
- def reset_rating
49
- ratings.destroy_all
50
- end
51
-
52
- # Redefine this method in your application's <tt>obj_extensions.rb</tt> in order to define conditions for allowing a CMS object to be rated.
53
- def allow_rating?; true; end
54
- # Redefine this method in your application's <tt>obj_extensions.rb</tt> in order to define conditions for allowing a CMS object to be rated anonymously.
55
- def allow_anonymous_rating?; true; end
56
- end
57
- end
@@ -1,52 +0,0 @@
1
- module RailsConnector
2
- # Search Engine Optimization methods
3
- module SEO
4
-
5
- # The methods contained herein are attached to the Obj model class.
6
- module ClassMethods
7
- # Finds all objects that shall be included in the SEO <tt>sitemap.xml</tt>.
8
- # On each exportable none-image object, {InstanceMethods#included_in_seo_sitemap?} is called.
9
- # Overwrite <tt>included_in_seo_sitemap?</tt> in your {Obj} to adjust the criteria.
10
- def find_all_for_sitemap
11
- start = Obj.homepage
12
- children = start.toclist
13
- grandchildren = children.map(&:toclist).flatten
14
-
15
- ([start] + children + grandchildren).select(&:included_in_seo_sitemap?)
16
- end
17
- end
18
-
19
- # The methods contained herein are included in the Obj model.
20
- module InstanceMethods
21
-
22
- # Returns +true+ by default. Overwrite in your {Obj} as you like.
23
- def readable_for_googlebots?
24
- true
25
- end
26
-
27
- # Default implementation: objects have to be <tt>active?</tt> and at least of one of: permitted for anyone (<tt>permitted_groups = []</tt>), <tt>readable_for_googlebots?</tt>.
28
- # Overwrite in your {Obj} as you like.
29
- def included_in_seo_sitemap?
30
- (permitted_groups.empty? || readable_for_googlebots?) && active?
31
- end
32
-
33
- # Returns an html-stripped <tt>Obj#body</tt>, truncated to 300 chars.
34
- # Overwrite in your {Obj} as you like. For example, point to a CMS field.
35
- def seo_description
36
- HTML::FullSanitizer.new.sanitize(body.strip.gsub(%r{[\n|\r]}, " ")).mb_chars[0,300] if body
37
- end
38
-
39
- # Returns +nil+ by default. Overwrite in your {Obj} as you like.
40
- # For example, point to a CMS field of your objects.
41
- def seo_keywords
42
- nil
43
- end
44
- end
45
-
46
- def self.included(receiver)
47
- receiver.extend ClassMethods
48
- receiver.send :include, InstanceMethods
49
- end
50
-
51
- end
52
- end