Module: PageSectionsHelper
- Defined in:
- app/helpers/page_sections_helper.rb
Overview
View helpers for the standard sections shared across WWW landing pages —
FAQ, videos, showcases, documents, blog posts, reviews, plus the
single-component sections (benefits, calculator, other products,
smartplan, comparison).
Each helper owns the full repetitive pattern in one place: the
records.present? guard, the page_section chrome (canonical id and
border), and the component render. A call site collapses from a ~6-line
if … page_section … render block to a single line, and a change to a
section's wrapper style (e.g. the FAQ border:) happens here once
instead of on ~60 landing pages — preventing content-style drift.
Records default to the page's tag-scoped set (see PagesHelper); pass an
explicit collection to override. Any further keyword arguments are
forwarded to the underlying component; the rare page_section override
goes via section:.
Pass fragment_cache: true to wrap a section in a fragment cache. It is
off by default — these pages are served from Cloudflare's edge cache, so
fragment caching is only an occasional optimisation.
Instance Method Summary collapse
-
#benefits_section(section: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard "Why Install" benefits section (mint-green band).
-
#calculator_section(section: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard floor-heating cost calculator section.
-
#comparison_section(section: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard product comparison-table section.
-
#documents_section(publications = page_publications, title: 'Documents', section: {}, fragment_cache: false) ⇒ ActiveSupport::SafeBuffer?
Renders the standard Documents section — publication PDFs.
-
#education_sections(videos: {}, documents: {}, posts: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard education sections — Videos, then Documents, then Articles — in that fixed order as one unit, so the trio always renders together and consistently ordered on every landing page (the same bundling approach as #social_proof_sections).
-
#faq_section(article_faqs = page_article_faqs, title: 'Frequently Asked Questions', section: {}, fragment_cache: false) ⇒ ActiveSupport::SafeBuffer?
Renders the standard FAQ section — the last section on a landing page.
-
#other_products_section(section: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard "Other Products" category-cards section.
-
#page_topic(value = nil) ⇒ String?
Renders the standard Articles section (blog posts).
-
#posts_section(posts = page_posts, title: nil, section: {}, fragment_cache: false) ⇒ ActiveSupport::SafeBuffer?
Nil — renders nothing — when empty.
-
#reviews_section(section: {}) ⇒ ActiveSupport::SafeBuffer?
Renders the standard Customer Reviews section.
-
#showcases_section(showcases = page_showcases, title: 'Featured Projects', section: {}, fragment_cache: false) ⇒ ActiveSupport::SafeBuffer?
Renders the standard Showcases ("Featured Projects") section.
-
#smartplan_section(section: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard "Request a SmartPlan" section.
-
#social_proof_sections(showcases = page_showcases, reviews: {}, **showcases_options) ⇒ ActiveSupport::SafeBuffer
Renders the Reviews section immediately followed by the Showcases section — the canonical "social proof" pairing (see the home page).
-
#videos_section(videos = page_videos, title: 'Videos', section: {}, fragment_cache: false) ⇒ ActiveSupport::SafeBuffer?
Renders the standard Videos section.
Instance Method Details
#benefits_section(section: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard "Why Install" benefits section (mint-green band).
All keyword arguments are forwarded to Www::BenefitsListComponent.
228 229 230 231 232 |
# File 'app/helpers/page_sections_helper.rb', line 228 def benefits_section(section: {}, **) page_section(id: 'why-install', container: :none, border: :none, background: :mint_green, **section) do render Www::BenefitsListComponent.new(**) end end |
#calculator_section(section: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard floor-heating cost calculator section.
All keyword arguments are forwarded to Www::FloorHeatingCalculatorComponent.
240 241 242 243 244 |
# File 'app/helpers/page_sections_helper.rb', line 240 def calculator_section(section: {}, **) page_section(id: 'floor-heating-calculator', **section) do render Www::FloorHeatingCalculatorComponent.new(**) end end |
#comparison_section(section: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard product comparison-table section.
All keyword arguments are forwarded to Www::ProductCompareTableComponent.
276 277 278 279 280 |
# File 'app/helpers/page_sections_helper.rb', line 276 def comparison_section(section: {}, **) page_section(id: 'comparison', **section) do render Www::ProductCompareTableComponent.new(**) end end |
#documents_section(publications = page_publications, title: 'Documents', section: {}, fragment_cache: false) ⇒ ActiveSupport::SafeBuffer?
Renders the standard Documents section — publication PDFs. (Blog posts
render separately via #posts_section.)
Extra keyword arguments are forwarded to Www::CardGridComponent.
106 107 108 109 110 111 112 113 114 |
# File 'app/helpers/page_sections_helper.rb', line 106 def documents_section(publications = page_publications, title: 'Documents', section: {}, fragment_cache: false, **) return if publications.blank? cached_section('documents', publications, enabled: fragment_cache) do page_section(id: 'documents', **section) do render Www::CardGridComponent.new(section_title: title, publications:, **) end end end |
#education_sections(videos: {}, documents: {}, posts: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard education sections — Videos, then Documents, then
Articles — in that fixed order as one unit, so the trio always renders
together and consistently ordered on every landing page (the same
bundling approach as #social_proof_sections).
Each section's options go in its own hash, forwarded to the underlying
helper. Pass a custom record collection via the records: key; omit it
to use that helper's tag-scoped default. A section with nothing to show
is skipped.
210 211 212 213 214 215 216 217 218 219 |
# File 'app/helpers/page_sections_helper.rb', line 210 def education_sections(videos: {}, documents: {}, posts: {}) safe_join( [[:videos_section, videos], [:documents_section, documents], [:posts_section, posts]].filter_map do |helper, opts| opts = opts.dup has_records = opts.key?(:records) records = opts.delete(:records) has_records ? send(helper, records, **opts) : send(helper, **opts) end ) end |
#faq_section(article_faqs = page_article_faqs, title: 'Frequently Asked Questions', section: {}, fragment_cache: false) ⇒ ActiveSupport::SafeBuffer?
Renders the standard FAQ section — the last section on a landing page.
Extra keyword arguments are forwarded to Www::FaqListComponent
(e.g. filter_tags:, initial_limit:).
44 45 46 47 48 49 50 51 52 |
# File 'app/helpers/page_sections_helper.rb', line 44 def faq_section(article_faqs = page_article_faqs, title: 'Frequently Asked Questions', section: {}, fragment_cache: false, **) return if article_faqs.blank? cached_section('faq', article_faqs, enabled: fragment_cache) do page_section(id: 'faq', border: :none, **section) do render Www::FaqListComponent.new(section_title: title, article_faqs:, **) end end end |
#other_products_section(section: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard "Other Products" category-cards section.
All keyword arguments are forwarded to Www::ProductCategoryCardsComponent.
252 253 254 255 256 |
# File 'app/helpers/page_sections_helper.rb', line 252 def other_products_section(section: {}, **) page_section(id: 'other-products', **section) do render Www::ProductCategoryCardsComponent.new(**) end end |
#page_topic(value = nil) ⇒ String?
Renders the standard Articles section (blog posts).
Extra keyword arguments are forwarded to Www::CardGridComponent.
Setter/getter for the page's SEO topic — the short noun phrase a page
is "about". Used as the leading term in related-content section
headings (see #posts_section). When unset, formatted_breadcrumb
auto-derives one by reverse-joining the breadcrumb crumb names —
[Floor Heating, Bathroom] → "Bathroom Floor Heating". Pages that
don't use breadcrumbs (or want a different phrase) can override:
<% page_topic 'Custom SEO Phrase' %>
131 132 133 134 |
# File 'app/helpers/page_sections_helper.rb', line 131 def page_topic(value = nil) @page_topic = value if value @page_topic end |
#posts_section(posts = page_posts, title: nil, section: {}, fragment_cache: false) ⇒ ActiveSupport::SafeBuffer?
Returns nil — renders nothing — when empty.
144 145 146 147 148 149 150 151 152 153 154 |
# File 'app/helpers/page_sections_helper.rb', line 144 def posts_section(posts = page_posts, title: nil, section: {}, fragment_cache: false, **) return if posts.blank? title ||= page_topic.present? ? "#{page_topic} Posts" : 'Posts' cached_section('posts', posts, enabled: fragment_cache) do page_section(id: 'posts', **section) do render Www::CardGridComponent.new(section_title: title, posts:, **) end end end |
#reviews_section(section: {}) ⇒ ActiveSupport::SafeBuffer?
Renders the standard Customer Reviews section.
All keyword arguments are forwarded to Www::ReviewsIo::ReviewSliderComponent
(e.g. tags:, product_line:, section_title:, see_all_url:, min_rating:).
The section — wrapper included — is omitted entirely when the component has
nothing to show (no matching reviews and no founder lead card).
165 166 167 168 169 170 171 172 |
# File 'app/helpers/page_sections_helper.rb', line 165 def reviews_section(section: {}, **) component = Www::ReviewsIo::ReviewSliderComponent.new(**) return unless component.render? page_section(id: 'reviews', **section) do render component end end |
#showcases_section(showcases = page_showcases, title: 'Featured Projects', section: {}, fragment_cache: false) ⇒ ActiveSupport::SafeBuffer?
Renders the standard Showcases ("Featured Projects") section.
Extra keyword arguments are forwarded to Www::ShowcaseGridComponent
(e.g. description:, view_more_title:, view_more_href:).
85 86 87 88 89 90 91 92 93 |
# File 'app/helpers/page_sections_helper.rb', line 85 def showcases_section(showcases = page_showcases, title: 'Featured Projects', section: {}, fragment_cache: false, **) return if showcases.blank? cached_section('showcases', showcases, enabled: fragment_cache) do page_section(id: 'showcases', **section) do render Www::ShowcaseGridComponent.new(section_title: title, showcases:, **) end end end |
#smartplan_section(section: {}) ⇒ ActiveSupport::SafeBuffer
Renders the standard "Request a SmartPlan" section.
All keyword arguments are forwarded to Www::RequestSmartplanSectionComponent.
264 265 266 267 268 |
# File 'app/helpers/page_sections_helper.rb', line 264 def smartplan_section(section: {}, **) page_section(id: 'request-smartplan', container: :none, **section) do render Www::RequestSmartplanSectionComponent.new(**) end end |
#social_proof_sections(showcases = page_showcases, reviews: {}, **showcases_options) ⇒ ActiveSupport::SafeBuffer
Renders the Reviews section immediately followed by the Showcases
section — the canonical "social proof" pairing (see the home page).
Bundling them in one call guarantees the two render adjacent and in
this order on every landing page, so the pairing cannot drift apart.
Showcase records and showcases_section options are passed exactly as
to #showcases_section; Reviews options go in the reviews: hash and
are forwarded to #reviews_section. Either section is omitted when it
has nothing to show.
189 190 191 192 193 194 |
# File 'app/helpers/page_sections_helper.rb', line 189 def (showcases = page_showcases, reviews: {}, **) safe_join([ reviews_section(**reviews), showcases_section(showcases, **) ].compact) end |
#videos_section(videos = page_videos, title: 'Videos', section: {}, fragment_cache: false) ⇒ ActiveSupport::SafeBuffer?
Renders the standard Videos section.
Extra keyword arguments are forwarded to Www::VideoSectionComponent.
64 65 66 67 68 69 70 71 72 |
# File 'app/helpers/page_sections_helper.rb', line 64 def videos_section(videos = page_videos, title: 'Videos', section: {}, fragment_cache: false, **) return if videos.blank? cached_section('videos', videos, enabled: fragment_cache) do page_section(id: 'videos', **section) do render Www::VideoSectionComponent.new(section_title: title, videos:, **) end end end |