Class: Refinery::Page
- Inherits:
-
Core::BaseModel
- Object
- Core::BaseModel
- Refinery::Page
- Extended by:
- FriendlyId
- Defined in:
- app/models/refinery/page.rb
Defined Under Namespace
Classes: Translation
Constant Summary collapse
- PATH_SEPARATOR =
when collecting the pages path how is each of the pages seperated?
" - "
Instance Attribute Summary collapse
-
#locale ⇒ Object
to hold temporarily.
-
#page_menu_title ⇒ Object
to hold temporarily.
-
#page_title ⇒ Object
to hold temporarily.
Class Method Summary collapse
-
.by_slug(slug, conditions = {}) ⇒ Object
Finds a page using its slug.
-
.by_title(title) ⇒ Object
Finds a page using its title.
-
.different_frontend_locale? ⇒ Boolean
Wraps up all the checks that we need to do to figure out whether the current frontend locale is different to the current one set by ::I18n.locale.
- .expire_page_caching ⇒ Object
-
.fast_menu(columns = []) ⇒ Object
Because pages are translated this can have a negative performance impact on your website and can introduce scaling issues.
-
.find_by_path(path) ⇒ Object
With slugs scoped to the parent page we need to find a page by its full path.
-
.find_by_path_or_id(path, id) ⇒ Object
Helps to resolve the situation where you have a path and an id and if the path is unfriendly then a different finder method is required than find_by_path.
-
.in_menu ⇒ Object
Shows all pages with :show_in_menu set to true, but it also rejects any page that has not been translated to the current locale.
-
.live ⇒ Object
Live pages are ‘allowed’ to be shown in the frontend of your website.
-
.menu_columns ⇒ Object
Override this method to change which columns you want to select to render your menu.
-
.per_page(dialog = false) ⇒ Object
Returns how many pages per page should there be when paginating pages.
- .rebuild_with_invalidate_cached_urls! ⇒ Object
-
.with_globalize(conditions = {}) ⇒ Object
Wrap up the logic of finding the pages based on the translations table.
Instance Method Summary collapse
-
#all_page_part_content ⇒ Object
Used to index all the content on this page so it can be easily searched.
- #cache_key(locale) ⇒ Object
-
#canonical ⇒ Object
The canonical page for this particular page.
-
#content_for(part_title) ⇒ Object
Accessor method to get a page part from a page.
-
#custom_slug_or_title ⇒ Object
Returns in cascading order: custom_slug or menu_title or title depending on which attribute is first found to be present for this page.
-
#deletable? ⇒ Boolean
Am I allowed to delete this page? If a link_url is set we don’t want to break the link so we don’t allow them to delete If deletable is set to false then we don’t allow this page to be deleted.
-
#destroy ⇒ Object
Before destroying a page we check to see if it’s a deletable page or not Refinery system pages are not deletable.
-
#destroy! ⇒ Object
If you want to destroy a page that is set to be not deletable this is the way to do it.
-
#home? ⇒ Boolean
Returns true if this page is the home page or links to it.
-
#in_menu? ⇒ Boolean
Return true if this page can be shown in the navigation.
-
#link_url_localised? ⇒ Boolean
Adds the locale key into the URI for this page’s link_url attribute, unless the current locale is set as the default locale.
-
#live? ⇒ Boolean
Returns true if this page is “published”.
-
#nested_path ⇒ Object
Returns the string version of nested_url, i.e., the path that should be generated by the router.
-
#normalize_friendly_id_with_marketable_urls(slug_string) ⇒ Object
Protects generated slugs from title if they are in the list of reserved words This applies mostly to plugin-generated pages.
- #not_in_menu? ⇒ Boolean
-
#part_with_title(part_title) ⇒ Object
Accessor method to get a page part object from a page.
-
#path(options = {}) ⇒ Object
Used for the browser title to get the full path to this page It automatically prints out this page title and all of it’s parent page titles joined by a PATH_SEPARATOR.
- #path_cache_key(locale = Globalize.locale) ⇒ Object
- #refinery_menu_title ⇒ Object
-
#reposition_parts! ⇒ Object
Repositions the child page_parts that belong to this page.
-
#shown_siblings ⇒ Object
Returns all visible sibling pages that can be rendered for the menu.
-
#title_with_meta ⇒ Object
In the admin area we use a slightly different title to inform the which pages are draft or hidden pages We show the title from the next available locale if there is no title for the current locale.
- #to_refinery_menu_item ⇒ Object
- #uncached_nested_url ⇒ Object (also: #nested_url)
-
#url ⇒ Object
When this page is rendered in the navigation, where should it link? If a custom “link_url” is set, it uses that otherwise it defaults to a normal page URL.
- #url_cache_key(locale = Globalize.locale) ⇒ Object
-
#url_marketable ⇒ Object
Add ‘marketable url’ attributes into this page’s url.
-
#url_normal ⇒ Object
Returns a url suitable to be used in url_for in Rails (such as link_to).
-
#with_locale_param(url_hash, locale = nil) ⇒ Object
If the current locale is set to something other than the default locale then the :locale attribute will be set on the url hash, otherwise it won’t be.
Instance Attribute Details
#locale ⇒ Object
to hold temporarily
32 33 34 |
# File 'app/models/refinery/page.rb', line 32 def locale @locale end |
#page_menu_title ⇒ Object
to hold temporarily
32 33 34 |
# File 'app/models/refinery/page.rb', line 32 def @page_menu_title end |
#page_title ⇒ Object
to hold temporarily
32 33 34 |
# File 'app/models/refinery/page.rb', line 32 def page_title @page_title end |
Class Method Details
.by_slug(slug, conditions = {}) ⇒ Object
Finds a page using its slug. See by_title
107 108 109 110 |
# File 'app/models/refinery/page.rb', line 107 def by_slug(slug, conditions={}) locales = Refinery.i18n_enabled? ? Refinery::I18n.frontend_locales : ::I18n.locale with_globalize({ :locale => locales, :slug => slug }.merge(conditions)) end |
.by_title(title) ⇒ Object
Finds a page using its title. This method is necessary because pages are translated which means the title attribute does not exist on the pages table thus requiring us to find the attribute on the translations table and then join to the pages table again to return the associated record.
102 103 104 |
# File 'app/models/refinery/page.rb', line 102 def by_title(title) with_globalize(:title => title) end |
.different_frontend_locale? ⇒ Boolean
Wraps up all the checks that we need to do to figure out whether the current frontend locale is different to the current one set by ::I18n.locale. This terminates in a false if i18n extension is not defined or enabled.
165 166 167 |
# File 'app/models/refinery/page.rb', line 165 def different_frontend_locale? ::Refinery.i18n_enabled? && ::Refinery::I18n.current_frontend_locale != ::I18n.locale end |
.expire_page_caching ⇒ Object
180 181 182 183 184 185 186 187 188 189 |
# File 'app/models/refinery/page.rb', line 180 def expire_page_caching begin Rails.cache.delete_matched(/.*pages.*/) rescue NotImplementedError Rails.cache.clear warn "**** [REFINERY] The cache store you are using is not compatible with Rails.cache#delete_matched - clearing entire cache instead ***" ensure return true # so that other callbacks process. end end |
.fast_menu(columns = []) ⇒ Object
Because pages are translated this can have a negative performance impact on your website and can introduce scaling issues. What fast_menu does is finds all of the columns necessary to render a Refinery::Menu
structure using only one SQL query. This has limitations, including not being able to access any other attributes of the pages but you can specify more columns by passing in an array e.g. fast_menu([:column1, :column2])
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'app/models/refinery/page.rb', line 126 def (columns = []) # First, apply a filter to determine which pages to show. pages = live..order('lft ASC').includes(:translations) # Now we only want to select particular columns to avoid any further queries. # Title and menu_title are retrieved in the next block below so they are not here. ( | columns).each do |column| pages = pages.select(arel_table[column.to_sym]) end # We have to get title and menu_title from the translations table. # To avoid calling globalize3 an extra time, we get title as page_title # and we get menu_title as page_menu_title. # These is used in 'to_refinery_menu_item' in the Page model. %w(title menu_title).each do |column| pages = pages.joins(:translations).select( "#{translation_class.table_name}.#{column} as page_#{column}" ) end pages end |
.find_by_path(path) ⇒ Object
With slugs scoped to the parent page we need to find a page by its full path. For example with about/example we would need to find ‘about’ and then its child called ‘example’ otherwise it may clash with another page called /example.
75 76 77 78 79 80 81 |
# File 'app/models/refinery/page.rb', line 75 def find_by_path(path) split_path = path.to_s.split('/').reject(&:blank?) page = ::Refinery::Page.by_slug(split_path.shift, :parent_id => nil).first page = page.children.by_slug(split_path.shift).first until page.nil? || split_path.empty? page end |
.find_by_path_or_id(path, id) ⇒ Object
Helps to resolve the situation where you have a path and an id and if the path is unfriendly then a different finder method is required than find_by_path.
86 87 88 89 90 91 92 93 94 95 96 |
# File 'app/models/refinery/page.rb', line 86 def find_by_path_or_id(path, id) if Refinery::Pages.marketable_urls && path.present? if path.friendly_id? find_by_path(path) else find(path) end elsif id.present? find(id) end end |
.in_menu ⇒ Object
Shows all pages with :show_in_menu set to true, but it also rejects any page that has not been translated to the current locale. This works using a query against the translated content first and then using all of the page_ids we further filter against this model’s table.
116 117 118 |
# File 'app/models/refinery/page.rb', line 116 def where(:show_in_menu => true).with_globalize end |
.live ⇒ Object
Live pages are ‘allowed’ to be shown in the frontend of your website. By default, this is all pages that are not set as ‘draft’.
68 69 70 |
# File 'app/models/refinery/page.rb', line 68 def live where(:draft => false) end |
.menu_columns ⇒ Object
Override this method to change which columns you want to select to render your menu. title and menu_title are always retrieved so omit these.
171 172 173 |
# File 'app/models/refinery/page.rb', line 171 def %w(id depth parent_id lft rgt link_url menu_match slug) end |
.per_page(dialog = false) ⇒ Object
Returns how many pages per page should there be when paginating pages
176 177 178 |
# File 'app/models/refinery/page.rb', line 176 def per_page(dialog = false) dialog ? Pages.pages_per_dialog : Pages.pages_per_admin_index end |
.rebuild_with_invalidate_cached_urls! ⇒ Object
191 192 193 194 |
# File 'app/models/refinery/page.rb', line 191 def rebuild_with_invalidate_cached_urls! rebuild_without_invalidate_cached_urls! find_each { |page| page.send :invalidate_cached_urls } end |
.with_globalize(conditions = {}) ⇒ Object
Wrap up the logic of finding the pages based on the translations table.
150 151 152 153 154 155 156 157 158 159 160 |
# File 'app/models/refinery/page.rb', line 150 def with_globalize(conditions = {}) conditions = {:locale => ::Globalize.locale}.merge(conditions) globalized_conditions = {} conditions.keys.each do |key| if (translated_attribute_names.map(&:to_s) | %w(locale)).include?(key.to_s) globalized_conditions["#{self.translation_class.table_name}.#{key}"] = conditions.delete(key) end end # A join implies readonly which we don't really want. joins(:translations).where(globalized_conditions).where(conditions).readonly(false) end |
Instance Method Details
#all_page_part_content ⇒ Object
Used to index all the content on this page so it can be easily searched.
433 434 435 |
# File 'app/models/refinery/page.rb', line 433 def all_page_part_content parts.map(&:body).join(" ") end |
#cache_key(locale) ⇒ Object
345 346 347 |
# File 'app/models/refinery/page.rb', line 345 def cache_key(locale) [Refinery::Core.base_cache_key, 'page', locale, id].compact.join('/') end |
#canonical ⇒ Object
The canonical page for this particular page. Consists of:
* The default locale's translated slug
201 202 203 |
# File 'app/models/refinery/page.rb', line 201 def canonical Globalize.with_locale(::Refinery::I18n.default_frontend_locale){ url } end |
#content_for(part_title) ⇒ Object
397 398 399 |
# File 'app/models/refinery/page.rb', line 397 def content_for(part_title) part_with_title(part_title).try(:body) end |
#custom_slug_or_title ⇒ Object
Returns in cascading order: custom_slug or menu_title or title depending on which attribute is first found to be present for this page.
207 208 209 |
# File 'app/models/refinery/page.rb', line 207 def custom_slug_or_title custom_slug.presence || .presence || title end |
#deletable? ⇒ Boolean
Am I allowed to delete this page? If a link_url is set we don’t want to break the link so we don’t allow them to delete If deletable is set to false then we don’t allow this page to be deleted. These are often Refinery system pages
214 215 216 |
# File 'app/models/refinery/page.rb', line 214 def deletable? deletable && link_url.blank? and .blank? end |
#destroy ⇒ Object
Before destroying a page we check to see if it’s a deletable page or not Refinery system pages are not deletable.
228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'app/models/refinery/page.rb', line 228 def destroy return super if deletable? unless Rails.env.test? # give useful feedback when trying to delete from console puts "This page is not deletable. Please use .destroy! if you really want it deleted " puts "unset .link_url," if link_url.present? puts "unset .menu_match," if .present? puts "set .deletable to true" unless deletable end false end |
#destroy! ⇒ Object
If you want to destroy a page that is set to be not deletable this is the way to do it.
243 244 245 246 247 248 249 |
# File 'app/models/refinery/page.rb', line 243 def destroy! self. = nil self.link_url = nil self.deletable = true destroy end |
#home? ⇒ Boolean
Returns true if this page is the home page or links to it.
365 366 367 |
# File 'app/models/refinery/page.rb', line 365 def home? link_url == '/' end |
#in_menu? ⇒ Boolean
Return true if this page can be shown in the navigation. If it’s a draft or is set to not show in the menu it will return false.
356 357 358 |
# File 'app/models/refinery/page.rb', line 356 def live? && end |
#link_url_localised? ⇒ Boolean
Adds the locale key into the URI for this page’s link_url attribute, unless the current locale is set as the default locale.
285 286 287 288 289 290 291 292 293 294 295 |
# File 'app/models/refinery/page.rb', line 285 def link_url_localised? return link_url unless ::Refinery.i18n_enabled? current_url = link_url if current_url =~ %r{^/} && ::Refinery::I18n.current_frontend_locale != ::Refinery::I18n.default_frontend_locale current_url = "/#{::Refinery::I18n.current_frontend_locale}#{current_url}" end current_url end |
#live? ⇒ Boolean
Returns true if this page is “published”
350 351 352 |
# File 'app/models/refinery/page.rb', line 350 def live? not draft? end |
#nested_path ⇒ Object
Returns the string version of nested_url, i.e., the path that should be generated by the router
333 334 335 |
# File 'app/models/refinery/page.rb', line 333 def nested_path Rails.cache.fetch(path_cache_key) { ['', nested_url].join('/') } end |
#normalize_friendly_id_with_marketable_urls(slug_string) ⇒ Object
Protects generated slugs from title if they are in the list of reserved words This applies mostly to plugin-generated pages. This only kicks in when Refinery::Pages.marketable_urls is enabled.
Returns the sluggified string
443 444 445 446 447 448 449 |
# File 'app/models/refinery/page.rb', line 443 def normalize_friendly_id_with_marketable_urls(slug_string) sluggified = slug_string.to_slug.normalize! if Refinery::Pages.marketable_urls && self.class.friendly_id_config.reserved_words.include?(sluggified) sluggified << "-page" end sluggified end |
#not_in_menu? ⇒ Boolean
360 361 362 |
# File 'app/models/refinery/page.rb', line 360 def not end |
#part_with_title(part_title) ⇒ Object
407 408 409 410 411 412 413 414 415 |
# File 'app/models/refinery/page.rb', line 407 def part_with_title(part_title) # self.parts is usually already eager loaded so we can now just grab # the first element matching the title we specified. self.parts.detect do |part| part.title.present? and # protecting against the problem that occurs when have nil title part.title == part_title.to_s or part.title.downcase.gsub(" ", "_") == part_title.to_s.downcase.gsub(" ", "_") end end |
#path(options = {}) ⇒ Object
Used for the browser title to get the full path to this page It automatically prints out this page title and all of it’s parent page titles joined by a PATH_SEPARATOR
253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'app/models/refinery/page.rb', line 253 def path( = {}) # Override default options with any supplied. = {:reversed => true}.merge() unless parent_id.nil? parts = [title, parent.path()] parts.reverse! if [:reversed] parts.join(PATH_SEPARATOR) else title end end |
#path_cache_key(locale = Globalize.locale) ⇒ Object
337 338 339 |
# File 'app/models/refinery/page.rb', line 337 def path_cache_key(locale = Globalize.locale) [cache_key(locale), 'nested_path'].join('#') end |
#refinery_menu_title ⇒ Object
374 375 376 |
# File 'app/models/refinery/page.rb', line 374 def [, page_title, , title].detect(&:present?) end |
#reposition_parts! ⇒ Object
Repositions the child page_parts that belong to this page. This ensures that they are in the correct 0,1,2,3,4… etc order.
220 221 222 223 224 |
# File 'app/models/refinery/page.rb', line 220 def reposition_parts! reload.parts.each_with_index do |part, index| part.update_attribute(:position, index) end end |
#shown_siblings ⇒ Object
Returns all visible sibling pages that can be rendered for the menu
370 371 372 |
# File 'app/models/refinery/page.rb', line 370 def shown_siblings siblings.reject(&:not_in_menu?) end |
#title_with_meta ⇒ Object
In the admin area we use a slightly different title to inform the which pages are draft or hidden pages We show the title from the next available locale if there is no title for the current locale
419 420 421 422 423 424 425 426 427 428 429 430 |
# File 'app/models/refinery/page.rb', line 419 def if self.title.present? title = [self.title] else title = [self.translations.detect {|t| t.title.present?}.title] end title << "<em>(#{::I18n.t('hidden', :scope => 'refinery.admin.pages.page')})</em>" unless title << "<em>(#{::I18n.t('draft', :scope => 'refinery.admin.pages.page')})</em>" if draft? title.join(' ') end |
#to_refinery_menu_item ⇒ Object
378 379 380 381 382 383 384 385 386 387 388 389 |
# File 'app/models/refinery/page.rb', line 378 def { :id => id, :lft => lft, :menu_match => , :parent_id => parent_id, :rgt => rgt, :title => , :type => self.class.name, :url => url } end |
#uncached_nested_url ⇒ Object Also known as: nested_url
319 320 321 |
# File 'app/models/refinery/page.rb', line 319 def uncached_nested_url [parent.try(:uncached_nested_url), to_param.to_s].compact.flatten end |
#url ⇒ Object
When this page is rendered in the navigation, where should it link? If a custom “link_url” is set, it uses that otherwise it defaults to a normal page URL. The “link_url” is often used to link to a plugin rather than a page.
For example if I had a “Contact” page I don’t want it to just render a contact us page I want it to show the Inquiries form so I can collect inquiries. So I would set the “link_url” to “/contact”
273 274 275 276 277 278 279 280 281 |
# File 'app/models/refinery/page.rb', line 273 def url if link_url.present? link_url_localised? elsif Refinery::Pages.marketable_urls with_locale_param url_marketable elsif to_param.present? with_locale_param url_normal end end |
#url_cache_key(locale = Globalize.locale) ⇒ Object
341 342 343 |
# File 'app/models/refinery/page.rb', line 341 def url_cache_key(locale = Globalize.locale) [cache_key(locale), 'nested_url'].join('#') end |
#url_marketable ⇒ Object
Add ‘marketable url’ attributes into this page’s url. This sets ‘path’ as the nested_url value and sets ‘id’ to nil. For example, this might evaluate to /about for the “About” page.
300 301 302 303 |
# File 'app/models/refinery/page.rb', line 300 def url_marketable # :id => nil is important to prevent any other params[:id] from interfering with this route. url_normal.merge :path => nested_url, :id => nil end |
#url_normal ⇒ Object
Returns a url suitable to be used in url_for in Rails (such as link_to). For example, this might evaluate to /pages/about for the “About” page.
307 308 309 |
# File 'app/models/refinery/page.rb', line 307 def url_normal {:controller => '/refinery/pages', :action => 'show', :path => nil, :id => to_param, :only_path => true} end |
#with_locale_param(url_hash, locale = nil) ⇒ Object
If the current locale is set to something other than the default locale then the :locale attribute will be set on the url hash, otherwise it won’t be.
313 314 315 316 317 |
# File 'app/models/refinery/page.rb', line 313 def with_locale_param(url_hash, locale = nil) locale ||= ::Refinery::I18n.current_frontend_locale if self.class.different_frontend_locale? url_hash.update :locale => locale if locale url_hash end |