rails haml if add class - ruby-on-rails

How can I write this code in haml without repeating the render line?
- if i % 2 == 0
%section.wrapper-md.list
= render partial: 'property'
- else
%section.wrapper-md.list.background-gray
= render partial: 'property'
Thanks!!

Try something like this
%section.wrapper-md.list{class: ('background-gray' if i.even?)}
= render partial: 'property'
Also you could try using the cycle helper and no need for counters
%section.wrapper-md.list{class: cycle('', 'background-gray')}
= render partial: 'property'

Related

How to pass a parameter from a partial layout to a partial?

I want to display a form partial within a shared partial layout form_layout
# views/layouts/shared/_form_layout.html.haml
= form_with(model: record, remote: true) do |form|
.fields
= yield
/// other stuff
# views/articles/_form.html.haml
# ?? want to access the form builder here
# views/articles/new.html.haml
= render partial: 'form', layout: 'layouts/shared/form_layout', locals: { record: Article.new }
How can I access the FormBuilder object inside the partial template?
You should try this-
= render layout: "layouts/shared/form_layout", locals: { record: Article.new} do
# block contents..

Rails Locals - Passing Connected Model Data

My model structure is pretty solid. I have MarketingDeliverySystem has_many MarketingSections. MarketingSections has_many MarketingVideos.
I have another segment: GroupDevelopment has_many GroupSections. GroupSections has_many GroupVideos.
I'm trying to use a partial to pass the variables, thus DRYing it all up.
I have the following that I'm trying to pass to the partial:
= render partial: '/sales_presentations/sales_presentation',
locals: { marketing_delivery_system: #marketing_delivery_system,
first_video: first_marketing_video(#marketing_delivery_system),
sales_presentation: #marketing_delivery_system}
Then in the partial I have the following:
.rounded-box-header.blue-bg #{sales_presentation.title}
ul
- sales_presentation.sections.ordered.each_with_index do |section, index|
- list_class = 'section show'
- list_class = 'section hide' if index != 0
li
= link_to section.title, '#', class: 'section', data: { id: section.id }
ul class="#{list_class}" data-section-id="#{section.id}"
- section.videos.ordered.each do |video|
li.video
= link_to video.title, '#',
class: 'video video-link',
data: { video: video.youtube_link,
sales_presentation: sales_presentation.title.parameterize }
.seven.columns
.row
div id="#{sales_presentation.title.parameterize}-container"
video {
id="#{sales_presentation.title.parameterize}-video-player"
class="video-js vjs-default-skin videos"
height=400
poster=""
controls preload='none'
data-default-url="#{first_video(sales_presentation)&.youtube_link}"
I previously had issues with sales_presentation.title at the top until I updated the locals.
My question/issue is how do I pass in through the locals to use for sales_presentation.sections instead to use #marketing_delivery_system.marketing.sections?
I thought I could just put that in through locals:
sales_presentation.sections: #marketing_delivery_system.marketing_sections but I end up with a massive syntax error.
I've also tried creating a partial view for these two and then changed sales_presentation throughout the view to mod. Then changed mod.sections to mod_section and setting that in the locals to mod_section: #marketing_delivery_system.marketing_section. The problem then gets into that I end up needing to hit video later in the iteration. So then that has the same issue.
You misunderstand the meaning of locals in partials.
Says we have
<%= render partial: 'image', locals: {size: #image.size, extension: #image.extension} %>
It means that in image partial now we can use local variable size and extension (keys) as #image.size and #image.extension (values).
Put in locals: {} all local variables you want.
So you can't write in locals sales_presentation.sections: #marketing_delivery_system.marketing.sections
But you can sales_presentation_sections: #marketing_delivery_system.marketing.section
Also you have problem with this code:
locals: { marketing_delivery_system: #marketing_delivery_system,
first_video: first_marketing_video(#marketing_delivery_system),
sales_presentation: #marketing_delivery_system }
marketing_delivery_system and sales_presentation will be with the same value.

How can I DRY up conditional content_for in Rails view?

contests/show.html.haml:
- if modal
- content_for(:modal_header) do
= render 'contests/contest_header'
- content_for(:modal_body) do
= render 'contests/contest_body'
- else
= render 'contests/contest_header'
= render 'contests/contest_body'
modal is a boolean local which indicates whether the view is being rendered in a modal template, vs the regular application template. The modal has content_for blocks while the main application template does not:
layouts/modal.html.haml:
-modal = true
.modal-header
.row
.col-xs-11
= yield(:modal_header)
.col-xs-1
%button{'type': 'button', 'class': 'close', 'data-dismiss': 'modal', 'aria-label': 'close'}
%span{'aria-hidden': 'true'} ×
.modal-body
= render 'layouts/messages'
- if content_for?(:modal_body)
= yield(:modal_body)
- else
=yield
What I'm looking for is something that can conditionally make the content_for blocks disable when modal is false. Rather than repeating my render statements.
Found a solution from another SO answer! https://stackoverflow.com/a/27398070/378622
Here's my implementation
# app/helpers/application_helper.rb
def modal_content_for(name, &block)
if params[:modal] == '1'
content_for 'modal_' + name.to_s, nil, &block
else
capture_haml(&block)
end
end

Rails - Know caller filename when using render layout

I want to dynamically add classes to a container based on the name of the class that called my layout using the render method. Is it possible or do I need to pass it manually from each view?
File: emails/inbox.html.haml
render layout: 'shared/v3/panel' do
// whatever
Rendered HTML:
<div id="inbox" class="panel email_container"></div>
My temp solution is to do:
render layout: 'shared/v3/panel', locals: {class_panel: 'email_container', id_panel: 'inbox'} do
// whatever
But I want to do that dynamically.
Final solution: views/shared/_panel.html.haml
- # You need to use: "render layout", not "render partial" to pass the "do" block.
.container_content{class: "#{controller_name}_container #{local_assigns[:panel_class] ? panel_class : ''}", id: action_name}
- if local_assigns[:title]
.headline= local_assigns[:title]
= yield
- if local_assigns[:footer]
.footer= local_assigns[:footer]
- # Example of use:
-#= render layout: 'shared/v3/panel', locals: {title: 'Place', panel_class: 'my_custom_class'} do
-# - if #activity.place.present?
-# %p
-# = t('place')
-# = #activity.place

Rails same render partial as html string ?

So I come across with a problem where I would like to save a partial as an html string and render another partial with that string but I keep getting a double render error
def fruits
fruits = Fruits.all
market_html = "#{render partial: 'market', locals: {fruits: fruits}}"
render partial: 'super_market', locals {market_html: market_html}
end
Do you want render_to_string?
market_html = render_to_string partial: 'market', locals: {fruits: fruits}

Resources