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) ⇒ 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.
-
.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 ⇒ Object
-
#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.
-
#nested_url ⇒ Object
Returns an array with all ancestors to_param, allow with its own Ex: with an About page and a Mission underneath, ::Refinery::Page.find(‘mission’).nested_url would return:.
-
#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 ⇒ 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
-
#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 ⇒ 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) ⇒ 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
31 32 33 |
# File 'app/models/refinery/page.rb', line 31 def locale @locale end |
#page_menu_title ⇒ Object
to hold temporarily
31 32 33 |
# File 'app/models/refinery/page.rb', line 31 def @page_menu_title end |
#page_title ⇒ Object
to hold temporarily
31 32 33 |
# File 'app/models/refinery/page.rb', line 31 def page_title @page_title end |
Class Method Details
.by_slug(slug) ⇒ Object
Finds a page using its slug. See by_title
106 107 108 109 110 111 112 |
# File 'app/models/refinery/page.rb', line 106 def by_slug(slug) if defined?(::Refinery::I18n) with_globalize(:locale => Refinery::I18n.frontend_locales, :slug => slug) else with_globalize(:locale => ::I18n.locale, :slug => slug) end 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.
101 102 103 |
# File 'app/models/refinery/page.rb', line 101 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.
167 168 169 |
# File 'app/models/refinery/page.rb', line 167 def different_frontend_locale? ::Refinery.i18n_enabled? && ::Refinery::I18n.current_frontend_locale != ::I18n.locale end |
.expire_page_caching ⇒ Object
182 183 184 185 186 187 188 189 190 191 |
# File 'app/models/refinery/page.rb', line 182 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])
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'app/models/refinery/page.rb', line 128 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.
74 75 76 77 78 79 80 |
# File 'app/models/refinery/page.rb', line 74 def find_by_path(path) split_path = path.to_s.split('/') page = ::Refinery::Page.by_slug(split_path.shift).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.
85 86 87 88 89 90 91 92 93 94 95 |
# File 'app/models/refinery/page.rb', line 85 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.
118 119 120 |
# File 'app/models/refinery/page.rb', line 118 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’.
67 68 69 |
# File 'app/models/refinery/page.rb', line 67 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.
173 174 175 |
# File 'app/models/refinery/page.rb', line 173 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
178 179 180 |
# File 'app/models/refinery/page.rb', line 178 def per_page(dialog = false) dialog ? Pages.pages_per_dialog : Pages.config.pages_per_admin_index end |
.with_globalize(conditions = {}) ⇒ Object
Wrap up the logic of finding the pages based on the translations table.
152 153 154 155 156 157 158 159 160 161 162 |
# File 'app/models/refinery/page.rb', line 152 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.
431 432 433 |
# File 'app/models/refinery/page.rb', line 431 def all_page_part_content parts.map(&:body).join(" ") end |
#cache_key ⇒ Object
343 344 345 |
# File 'app/models/refinery/page.rb', line 343 def cache_key [Refinery::Core.base_cache_key, 'page', ::I18n.locale, id].compact.join('/') end |
#content_for(part_title) ⇒ Object
395 396 397 |
# File 'app/models/refinery/page.rb', line 395 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.
196 197 198 199 200 201 202 203 204 |
# File 'app/models/refinery/page.rb', line 196 def custom_slug_or_title if custom_slug.present? custom_slug elsif .present? else title end 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
209 210 211 |
# File 'app/models/refinery/page.rb', line 209 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.
223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'app/models/refinery/page.rb', line 223 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.
238 239 240 241 242 243 244 |
# File 'app/models/refinery/page.rb', line 238 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.
363 364 365 |
# File 'app/models/refinery/page.rb', line 363 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.
354 355 356 |
# File 'app/models/refinery/page.rb', line 354 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.
280 281 282 283 284 285 286 287 288 289 290 |
# File 'app/models/refinery/page.rb', line 280 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”
348 349 350 |
# File 'app/models/refinery/page.rb', line 348 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
331 332 333 |
# File 'app/models/refinery/page.rb', line 331 def nested_path Rails.cache.fetch(path_cache_key) { ['', nested_url].join('/') } end |
#nested_url ⇒ Object
Returns an array with all ancestors to_param, allow with its own Ex: with an About page and a Mission underneath, ::Refinery::Page.find(‘mission’).nested_url would return:
['about', 'mission']
321 322 323 |
# File 'app/models/refinery/page.rb', line 321 def nested_url Rails.cache.fetch(url_cache_key) { uncached_nested_url } 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
441 442 443 444 445 446 447 |
# File 'app/models/refinery/page.rb', line 441 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
358 359 360 |
# File 'app/models/refinery/page.rb', line 358 def not end |
#part_with_title(part_title) ⇒ Object
405 406 407 408 409 410 411 412 413 |
# File 'app/models/refinery/page.rb', line 405 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
248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'app/models/refinery/page.rb', line 248 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 ⇒ Object
335 336 337 |
# File 'app/models/refinery/page.rb', line 335 def path_cache_key [cache_key, 'nested_path'].join('#') end |
#refinery_menu_title ⇒ Object
372 373 374 |
# File 'app/models/refinery/page.rb', line 372 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.
215 216 217 218 219 |
# File 'app/models/refinery/page.rb', line 215 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
368 369 370 |
# File 'app/models/refinery/page.rb', line 368 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
417 418 419 420 421 422 423 424 425 426 427 428 |
# File 'app/models/refinery/page.rb', line 417 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
376 377 378 379 380 381 382 383 384 385 386 387 |
# File 'app/models/refinery/page.rb', line 376 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
325 326 327 |
# File 'app/models/refinery/page.rb', line 325 def uncached_nested_url [parent.try(: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”
268 269 270 271 272 273 274 275 276 |
# File 'app/models/refinery/page.rb', line 268 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 ⇒ Object
339 340 341 |
# File 'app/models/refinery/page.rb', line 339 def url_cache_key [cache_key, '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.
295 296 297 298 |
# File 'app/models/refinery/page.rb', line 295 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.
302 303 304 |
# File 'app/models/refinery/page.rb', line 302 def url_normal {:controller => '/refinery/pages', :action => 'show', :path => nil, :id => to_param, :only_path => true} end |
#with_locale_param(url_hash) ⇒ 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.
308 309 310 311 312 313 |
# File 'app/models/refinery/page.rb', line 308 def with_locale_param(url_hash) if self.class.different_frontend_locale? url_hash.update(:locale => ::Refinery::I18n.current_frontend_locale) end url_hash end |