refinerycms-pages 0.9.9.1
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/app/controllers/admin/page_parts_controller.rb +24 -0
- data/app/controllers/admin/pages_controller.rb +37 -0
- data/app/controllers/admin/pages_dialogs_controller.rb +87 -0
- data/app/controllers/pages_controller.rb +31 -0
- data/app/helpers/pages_helper.rb +2 -0
- data/app/models/page.rb +274 -0
- data/app/models/page_part.rb +23 -0
- data/app/presenters/page_presenter.rb +7 -0
- data/app/views/admin/pages/_form.html.erb +61 -0
- data/app/views/admin/pages/_form_advanced_options.html.erb +79 -0
- data/app/views/admin/pages/_form_advanced_options_seo.html.erb +24 -0
- data/app/views/admin/pages/_form_fields_after_title.html.erb +1 -0
- data/app/views/admin/pages/_form_new_page_parts.html.erb +14 -0
- data/app/views/admin/pages/_form_page_parts.html.erb +47 -0
- data/app/views/admin/pages/_locale_picker.html.erb +11 -0
- data/app/views/admin/pages/_page.html.erb +35 -0
- data/app/views/admin/pages/_page_part_field.html.erb +5 -0
- data/app/views/admin/pages/_sortable_list.html.erb +5 -0
- data/app/views/admin/pages/edit.html.erb +1 -0
- data/app/views/admin/pages/index.html.erb +40 -0
- data/app/views/admin/pages/new.html.erb +1 -0
- data/app/views/admin/pages_dialogs/_page_link.html.erb +13 -0
- data/app/views/admin/pages_dialogs/link_to.html.erb +141 -0
- data/app/views/pages/home.html.erb +1 -0
- data/app/views/pages/show.html.erb +1 -0
- data/config/locales/cs.yml +84 -0
- data/config/locales/da.yml +84 -0
- data/config/locales/de.yml +84 -0
- data/config/locales/el.yml +84 -0
- data/config/locales/en.yml +84 -0
- data/config/locales/es.yml +83 -0
- data/config/locales/fr.yml +84 -0
- data/config/locales/it.yml +98 -0
- data/config/locales/lolcat.yml +83 -0
- data/config/locales/lt.yml +85 -0
- data/config/locales/lv.yml +86 -0
- data/config/locales/nb.yml +85 -0
- data/config/locales/nl.yml +81 -0
- data/config/locales/pl.yml +85 -0
- data/config/locales/pt-BR.yml +85 -0
- data/config/locales/rs.yml +84 -0
- data/config/locales/ru.yml +108 -0
- data/config/locales/sl.yml +83 -0
- data/config/locales/sv.yml +84 -0
- data/config/locales/vi.yml +84 -0
- data/config/locales/zh-CN.yml +84 -0
- data/config/locales/zh-TW.yml +84 -0
- data/config/routes.rb +21 -0
- data/db/migrate/20100913234708_create_refinerycms_pages_schema.rb +53 -0
- data/db/migrate/20101214040815_translate_page_plugin.rb +29 -0
- data/db/migrate/20101216194133_remove_cached_slug_from_pages.rb +9 -0
- data/db/seeds/pages.rb +43 -0
- data/features/manage_pages.feature +47 -0
- data/features/step_definitions/page_steps.rb +53 -0
- data/features/support/paths.rb +26 -0
- data/features/visit_pages.feature +47 -0
- data/lib/gemspec.rb +33 -0
- data/lib/generators/refinerycms_pages_generator.rb +8 -0
- data/lib/pages/marketable_routes.rb +10 -0
- data/lib/pages/tabs.rb +30 -0
- data/lib/refinerycms-pages.rb +45 -0
- data/license.md +21 -0
- data/readme.md +156 -0
- data/refinerycms-pages.gemspec +110 -0
- data/spec/models/page_spec.rb +144 -0
- metadata +133 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
module Admin
|
2
|
+
class PagePartsController < Admin::BaseController
|
3
|
+
|
4
|
+
def new
|
5
|
+
render :partial => "/admin/pages/page_part_field", :locals => {
|
6
|
+
:part => PagePart.new(:title => params[:title], :body => params[:body]),
|
7
|
+
:new_part => true,
|
8
|
+
:part_index => params[:part_index]
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def destroy
|
13
|
+
part = PagePart.find(params[:id])
|
14
|
+
page = part.page
|
15
|
+
if part.destroy
|
16
|
+
page.reposition_parts!
|
17
|
+
render :text => "'#{part.title}' deleted."
|
18
|
+
else
|
19
|
+
render :text => "'#{part.title}' not deleted."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Admin
|
2
|
+
class PagesController < Admin::BaseController
|
3
|
+
|
4
|
+
crudify :page,
|
5
|
+
:conditions => {:parent_id => nil},
|
6
|
+
:order => "lft ASC",
|
7
|
+
:include => [:parts, :slugs, :children, :parent, :translations],
|
8
|
+
:paging => false
|
9
|
+
|
10
|
+
rescue_from FriendlyId::ReservedError, :with => :show_errors_for_reserved_slug
|
11
|
+
|
12
|
+
def new
|
13
|
+
@page = Page.new
|
14
|
+
Page.default_parts.each_with_index do |page_part, index|
|
15
|
+
@page.parts << PagePart.new(:title => page_part, :position => index)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def globalize!
|
22
|
+
Thread.current[:globalize_locale] = (params[:switch_locale] || (@page.present? && @page.slug.present? && @page.slug.locale) || ::Refinery::I18n.default_frontend_locale)
|
23
|
+
end
|
24
|
+
|
25
|
+
def show_errors_for_reserved_slug(exception)
|
26
|
+
flash[:error] = t('reserved_system_word', :scope => 'admin.pages')
|
27
|
+
if params[:action] == 'update'
|
28
|
+
find_page
|
29
|
+
render :edit
|
30
|
+
else
|
31
|
+
@page = Page.new(params[:page])
|
32
|
+
render :new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Admin
|
4
|
+
class PagesDialogsController < Admin::DialogsController
|
5
|
+
|
6
|
+
crudify :page
|
7
|
+
|
8
|
+
def link_to
|
9
|
+
@pages = Page.paginate :page => params[:page],
|
10
|
+
:conditions => {:parent_id => nil},
|
11
|
+
:order => 'position ASC',
|
12
|
+
:per_page => Page.per_page(dialog=true)
|
13
|
+
|
14
|
+
if ::Refinery::Plugins.registered.names.include?('refinery_files')
|
15
|
+
@resources = Resource.paginate :page => params[:resource_page],
|
16
|
+
:order => 'created_at DESC',
|
17
|
+
:per_page => Resource.per_page(dialog=true)
|
18
|
+
|
19
|
+
# resource link
|
20
|
+
if params[:current_link].present?
|
21
|
+
is_resource_link = params[:current_link].include?("/system/resources")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# web address link
|
26
|
+
@web_address_text = "http://"
|
27
|
+
@web_address_text = params[:current_link] if params[:current_link].to_s =~ /^http:\/\//
|
28
|
+
@web_address_target_blank = (params[:target_blank] == "true")
|
29
|
+
|
30
|
+
# mailto link
|
31
|
+
if params[:current_link].present?
|
32
|
+
if params[:current_link] =~ /^mailto:/
|
33
|
+
@email_address_text = params[:current_link].split("mailto:")[1].split('?')[0]
|
34
|
+
end
|
35
|
+
@email_default_subject_text = params[:current_link].split('?subject=')[1] || params[:subject]
|
36
|
+
@email_default_body_text = params[:current_link].split('?body=')[1] || params[:body]
|
37
|
+
end
|
38
|
+
|
39
|
+
if params[:paginating].present?
|
40
|
+
@page_area_selected = (params[:paginating] == "your_page")
|
41
|
+
@resource_area_selected = (params[:paginating] == "resource_file")
|
42
|
+
else
|
43
|
+
@page_area_selected = (!is_resource_link and @web_address_text == "http://" and @email_address_text.blank?)
|
44
|
+
@web_address_area_selected = (@web_address_text != "http://")
|
45
|
+
@email_address_area_selected = @email_address_text.present?
|
46
|
+
@resource_area_selected = is_resource_link
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_url
|
51
|
+
unless params[:url].blank?
|
52
|
+
url = URI.parse(params[:url])
|
53
|
+
if url.host.nil? && params[:url].start_with?('/')
|
54
|
+
url.host = URI.parse(request.url).host
|
55
|
+
end
|
56
|
+
|
57
|
+
http = Net::HTTP.new(url.host)
|
58
|
+
request = Net::HTTP::Get.new(url.path.blank? ? "/" : url.path)
|
59
|
+
|
60
|
+
response = http.request request
|
61
|
+
|
62
|
+
render :json => {:result => case response
|
63
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
64
|
+
'success'
|
65
|
+
else
|
66
|
+
'failure'
|
67
|
+
end }
|
68
|
+
end
|
69
|
+
|
70
|
+
rescue
|
71
|
+
render :json => {:result => 'failure'}
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_email
|
75
|
+
unless params[:email].blank?
|
76
|
+
valid = params[:email] =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
|
77
|
+
|
78
|
+
render :json => if valid
|
79
|
+
{:result => 'success'}
|
80
|
+
else
|
81
|
+
{:result => 'failure'}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class PagesController < ApplicationController
|
2
|
+
|
3
|
+
# This action is usually accessed with the root path, normally '/'
|
4
|
+
def home
|
5
|
+
error_404 unless (@page = Page.where(:link_url => '/').first).present?
|
6
|
+
end
|
7
|
+
|
8
|
+
# This action can be accessed normally, or as nested pages.
|
9
|
+
# Assuming a page named "mission" that is a child of "about",
|
10
|
+
# you can access the pages with the following URLs:
|
11
|
+
#
|
12
|
+
# GET /pages/about
|
13
|
+
# GET /about
|
14
|
+
#
|
15
|
+
# GET /pages/mission
|
16
|
+
# GET /about/mission
|
17
|
+
#
|
18
|
+
def show
|
19
|
+
@page = Page.find("#{params[:path]}/#{params[:id]}".split('/').last)
|
20
|
+
|
21
|
+
if @page.try(:live?) || (refinery_user? && current_user.authorized_plugins.include?("refinery_pages"))
|
22
|
+
# if the admin wants this to be a "placeholder" page which goes to its first child, go to that instead.
|
23
|
+
if @page.skip_to_first_child && (first_live_child = @page.children.order('lft ASC').where(:draft=>false).first).present?
|
24
|
+
redirect_to first_live_child.url
|
25
|
+
end
|
26
|
+
else
|
27
|
+
error_404
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/app/models/page.rb
ADDED
@@ -0,0 +1,274 @@
|
|
1
|
+
require 'globalize3'
|
2
|
+
|
3
|
+
class Page < ActiveRecord::Base
|
4
|
+
|
5
|
+
translates :title, :meta_keywords, :meta_description, :browser_title if self.respond_to?(:translates)
|
6
|
+
attr_accessor :locale # to hold temporarily
|
7
|
+
validates :title, :presence => true
|
8
|
+
|
9
|
+
acts_as_nested_set
|
10
|
+
|
11
|
+
# Docs for friendly_id http://github.com/norman/friendly_id
|
12
|
+
has_friendly_id :title, :use_slug => true,
|
13
|
+
:default_locale => (::Refinery::I18n.default_frontend_locale rescue :en),
|
14
|
+
:reserved_words => %w(index new session login logout users refinery admin images wymiframe),
|
15
|
+
:approximate_ascii => RefinerySetting.find_or_set(:approximate_ascii, false, :scoping => "pages")
|
16
|
+
|
17
|
+
has_many :parts,
|
18
|
+
:class_name => "PagePart",
|
19
|
+
:order => "position ASC",
|
20
|
+
:inverse_of => :page,
|
21
|
+
:dependent => :destroy
|
22
|
+
|
23
|
+
accepts_nested_attributes_for :parts, :allow_destroy => true
|
24
|
+
|
25
|
+
# Docs for acts_as_indexed http://github.com/dougal/acts_as_indexed
|
26
|
+
acts_as_indexed :fields => [:title, :meta_keywords, :meta_description,
|
27
|
+
:custom_title, :browser_title, :all_page_part_content]
|
28
|
+
|
29
|
+
before_destroy :deletable?
|
30
|
+
after_save :reposition_parts!
|
31
|
+
after_save :invalidate_child_cached_url
|
32
|
+
|
33
|
+
scope :live, where(:draft => false)
|
34
|
+
|
35
|
+
# shows all pages with :show_in_menu set to true, but it also
|
36
|
+
# rejects any page that has not been translated to the current locale.
|
37
|
+
scope :in_menu, lambda {
|
38
|
+
pages = Arel::Table.new(Page.table_name)
|
39
|
+
translations = Arel::Table.new(Page.translations_table_name)
|
40
|
+
|
41
|
+
includes(:translations).where(:show_in_menu => true).where(
|
42
|
+
translations[:locale].eq(Globalize.locale)).where(pages[:id].eq(translations[:page_id]))
|
43
|
+
}
|
44
|
+
|
45
|
+
# when a dialog pops up to link to a page, how many pages per page should there be
|
46
|
+
PAGES_PER_DIALOG = 14
|
47
|
+
|
48
|
+
# when listing pages out in the admin area, how many pages should show per page
|
49
|
+
PAGES_PER_ADMIN_INDEX = 20
|
50
|
+
|
51
|
+
# when collecting the pages path how is each of the pages seperated?
|
52
|
+
PATH_SEPARATOR = " - "
|
53
|
+
|
54
|
+
# Am I allowed to delete this page?
|
55
|
+
# If a link_url is set we don't want to break the link so we don't allow them to delete
|
56
|
+
# If deletable is set to false then we don't allow this page to be deleted. These are often Refinery system pages
|
57
|
+
def deletable?
|
58
|
+
deletable && link_url.blank? and menu_match.blank?
|
59
|
+
end
|
60
|
+
|
61
|
+
# Repositions the child page_parts that belong to this page.
|
62
|
+
# This ensures that they are in the correct 0,1,2,3,4... etc order.
|
63
|
+
def reposition_parts!
|
64
|
+
parts.each_with_index do |part, index|
|
65
|
+
part.update_attribute(:position, index)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Before destroying a page we check to see if it's a deletable page or not
|
70
|
+
# Refinery system pages are not deletable.
|
71
|
+
def destroy
|
72
|
+
if deletable?
|
73
|
+
super
|
74
|
+
else
|
75
|
+
unless Rails.env.test?
|
76
|
+
# give useful feedback when trying to delete from console
|
77
|
+
puts "This page is not deletable. Please use .destroy! if you really want it deleted "
|
78
|
+
puts "unset .link_url," if link_url.present?
|
79
|
+
puts "unset .menu_match," if menu_match.present?
|
80
|
+
puts "set .deletable to true" unless deletable
|
81
|
+
end
|
82
|
+
|
83
|
+
return false
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# If you want to destroy a page that is set to be not deletable this is the way to do it.
|
88
|
+
def destroy!
|
89
|
+
self.menu_match = nil
|
90
|
+
self.link_url = nil
|
91
|
+
self.deletable = true
|
92
|
+
|
93
|
+
destroy
|
94
|
+
end
|
95
|
+
|
96
|
+
# Used for the browser title to get the full path to this page
|
97
|
+
# It automatically prints out this page title and all of it's parent page titles joined by a PATH_SEPARATOR
|
98
|
+
def path(options = {})
|
99
|
+
# Override default options with any supplied.
|
100
|
+
options = {:reversed => true}.merge(options)
|
101
|
+
|
102
|
+
unless parent.nil?
|
103
|
+
parts = [title, parent.path(options)]
|
104
|
+
parts.reverse! if options[:reversed]
|
105
|
+
parts.join(PATH_SEPARATOR)
|
106
|
+
else
|
107
|
+
title
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# When this page is rendered in the navigation, where should it link?
|
112
|
+
# If a custom "link_url" is set, it uses that otherwise it defaults to a normal page URL.
|
113
|
+
# The "link_url" is often used to link to a plugin rather than a page.
|
114
|
+
#
|
115
|
+
# For example if I had a "Contact" page I don't want it to just render a contact us page
|
116
|
+
# I want it to show the Inquiries form so I can collect inquiries. So I would set the "link_url"
|
117
|
+
# to "/contact"
|
118
|
+
def url
|
119
|
+
if link_url.present?
|
120
|
+
link_url_localised?
|
121
|
+
elsif self.class.use_marketable_urls?
|
122
|
+
url_marketable
|
123
|
+
elsif to_param.present?
|
124
|
+
url_normal
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def link_url_localised?
|
129
|
+
if link_url =~ %r{^/} and defined?(::Refinery::I18n) and ::Refinery::I18n.enabled? and
|
130
|
+
::I18n.locale != ::Refinery::I18n.default_frontend_locale
|
131
|
+
"/#{::I18n.locale}#{link_url}"
|
132
|
+
else
|
133
|
+
link_url
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def url_marketable
|
138
|
+
# :id => nil is important to prevent any other params[:id] from interfering with this route.
|
139
|
+
{:controller => '/pages', :action => 'show', :path => nested_url, :id => nil}
|
140
|
+
end
|
141
|
+
|
142
|
+
def url_normal
|
143
|
+
{:controller => '/pages', :action => 'show', :path => nil, :id => to_param}
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns an array with all ancestors to_param, allow with its own
|
147
|
+
# Ex: with an About page and a Mission underneath,
|
148
|
+
# Page.find('mission').nested_url would return:
|
149
|
+
#
|
150
|
+
# ['about', 'mission']
|
151
|
+
#
|
152
|
+
def nested_url
|
153
|
+
Rails.cache.fetch(url_cache_key) { uncached_nested_url }
|
154
|
+
end
|
155
|
+
|
156
|
+
def uncached_nested_url
|
157
|
+
[parent.try(:nested_url), to_param].compact.flatten
|
158
|
+
end
|
159
|
+
|
160
|
+
# Returns the string version of nested_url, i.e., the path that should be generated
|
161
|
+
# by the router
|
162
|
+
def nested_path
|
163
|
+
Rails.cache.fetch(path_cache_key) { ['', nested_url].join('/') }
|
164
|
+
end
|
165
|
+
|
166
|
+
def path_cache_key
|
167
|
+
[cache_key, 'nested_path'].join('#')
|
168
|
+
end
|
169
|
+
|
170
|
+
def url_cache_key
|
171
|
+
[cache_key, 'nested_url'].join('#')
|
172
|
+
end
|
173
|
+
|
174
|
+
def cache_key
|
175
|
+
[Refinery.base_cache_key, super].join('/')
|
176
|
+
end
|
177
|
+
|
178
|
+
# Returns true if this page is "published"
|
179
|
+
def live?
|
180
|
+
not draft?
|
181
|
+
end
|
182
|
+
|
183
|
+
# Return true if this page can be shown in the navigation.
|
184
|
+
# If it's a draft or is set to not show in the menu it will return false.
|
185
|
+
def in_menu?
|
186
|
+
live? && show_in_menu?
|
187
|
+
end
|
188
|
+
|
189
|
+
# Returns true if this page is the home page or links to it.
|
190
|
+
def home?
|
191
|
+
link_url == "/"
|
192
|
+
end
|
193
|
+
|
194
|
+
# Returns all visible sibling pages that can be rendered for the menu
|
195
|
+
def shown_siblings
|
196
|
+
siblings.reject { |sibling| not sibling.in_menu? }
|
197
|
+
end
|
198
|
+
|
199
|
+
class << self
|
200
|
+
# Accessor to find out the default page parts created for each new page
|
201
|
+
def default_parts
|
202
|
+
RefinerySetting.find_or_set(:default_page_parts, ["Body", "Side Body"])
|
203
|
+
end
|
204
|
+
|
205
|
+
# Returns how many pages per page should there be when paginating pages
|
206
|
+
def per_page(dialog = false)
|
207
|
+
dialog ? PAGES_PER_DIALOG : PAGES_PER_ADMIN_INDEX
|
208
|
+
end
|
209
|
+
|
210
|
+
def use_marketable_urls?
|
211
|
+
RefinerySetting.find_or_set(:use_marketable_urls, true, :scoping => 'pages')
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# Accessor method to get a page part from a page.
|
216
|
+
# Example:
|
217
|
+
#
|
218
|
+
# Page.first[:body]
|
219
|
+
#
|
220
|
+
# Will return the body page part of the first page.
|
221
|
+
def [](part_title)
|
222
|
+
# don't want to override a super method when trying to call a page part.
|
223
|
+
# the way that we call page parts seems flawed, will probably revert to page.parts[:title] in a future release.
|
224
|
+
if (super_value = super).blank?
|
225
|
+
# self.parts is already eager loaded so we can now just grab the first element matching the title we specified.
|
226
|
+
part = self.parts.detect do |part|
|
227
|
+
part.title.present? and #protecting against the problem that occurs when have nil title
|
228
|
+
part.title == part_title.to_s or
|
229
|
+
part.title.downcase.gsub(" ", "_") == part_title.to_s.downcase.gsub(" ", "_")
|
230
|
+
end
|
231
|
+
|
232
|
+
return part.body unless part.nil?
|
233
|
+
end
|
234
|
+
|
235
|
+
super_value
|
236
|
+
end
|
237
|
+
|
238
|
+
# In the admin area we use a slightly different title to inform the which pages are draft or hidden pages
|
239
|
+
def title_with_meta
|
240
|
+
title = [self.title.to_s]
|
241
|
+
title << "<em>(#{::I18n.t('hidden', :scope => 'admin.pages.page')})</em>" unless show_in_menu?
|
242
|
+
title << "<em>(#{::I18n.t('draft', :scope => 'admin.pages.page')})</em>" if draft?
|
243
|
+
|
244
|
+
title.join(' ')
|
245
|
+
end
|
246
|
+
|
247
|
+
# Used to index all the content on this page so it can be easily searched.
|
248
|
+
def all_page_part_content
|
249
|
+
parts.collect {|p| p.body}.join(" ")
|
250
|
+
end
|
251
|
+
|
252
|
+
##
|
253
|
+
# Protects generated slugs from title if they are in the list of reserved words
|
254
|
+
# This applies mostly to plugin-generated pages.
|
255
|
+
#
|
256
|
+
# Returns the sluggified string
|
257
|
+
def normalize_friendly_id(slug_string)
|
258
|
+
sluggified = super
|
259
|
+
if self.class.use_marketable_urls? && self.class.friendly_id_config.reserved_words.include?(sluggified)
|
260
|
+
sluggified << "-page"
|
261
|
+
end
|
262
|
+
sluggified
|
263
|
+
end
|
264
|
+
|
265
|
+
private
|
266
|
+
|
267
|
+
def invalidate_child_cached_url
|
268
|
+
return true unless self.class.use_marketable_urls?
|
269
|
+
children.each do |child|
|
270
|
+
Rails.cache.delete(child.url_cache_key)
|
271
|
+
Rails.cache.delete(child.path_cache_key)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|