constructing HTML with recursive loop in ruby on rails - html

Hello guys I have array of hashes:
#buttons = [{:serno=>1, :parent_serno=>0, :name=>"Home"},
{:serno=>2, :parent_serno=>0, :name=>"Search"},
{:serno=>3, :parent_serno=>0, :name=>"Search Payment"},
{:serno=>4, :parent_serno=>1, :name=>"Problematic Search Payment"},
{:serno=>5, :parent_serno=>1, :name=>"Cash Error"},
{:serno=>6, :parent_serno=>2, :name=>"Payment Note"},
{:serno=>7, :parent_serno=>2, :name=>"Search Payment By Category"},
{:serno=>8, :parent_serno=>3, :name=>"Search Payment New"},
{:serno=>9, :parent_serno=>3, :name=>"User Mangement"}]
I want to create div for each array hash (for example hash x) that's "parent_serno == 0", write their name inside the div and create another div inside of it, for every array hash that's "parent_serno == hash x [:serno]".
I tried to create partial:
<% for m in #buttons %>
<% unless #parent.present? %>
<% if m[:parent_serno] == 0 %>
<div>
<%= m[:name] %>
<% #parent = m[:serno] %>
<% if #buttons.find{ |b| b[:parent_serno] == #parent }.present? %>
<% #buttons.find{ |b| b[:parent_serno] == #parent }.each do %>
<%= render partial: "navbar", object: #parent %>
<% end %>
<% end %>
</div>
<% end%>
<% else %>
<% if m[:parent_serno] == #parent %>
<div>
<%= m[:name] %>
<% #parent = m[:serno] %>
<% if #buttons.find{ |b| b[:parent_serno] == #parent }.present? %>
<% #buttons.find{ |b| b[:parent_serno] == #parent }.each do %>
<%= render partial: "navbar", object: #parent %>
<% end %>
<% end %>
</div>
<% end%>
<% end %>
<% end %>
and render it in a another html.erb document, but apparently it just doesn't work :(
It only gives me the name of the first hash in the array and recursion stops there I guess.

I think the partial you need should look something like this:
_button.html.erb
<div>
<%= button[:name] %>
<% render partial: 'button',
collection: #buttons.select { |b| b[:parent_serno] == button[:serno] } %>
</div>
index.html.erb
...
<% render partial: 'button',
collection: #buttons.select { |b| b[:parent_serno] == 0 } %>
...

Related

ActionView::SyntaxErrorInTemplate in AccountsController#profile

Unexpected end when end exists, But I don't see where the issue is.
My terminal keeps giving me the error: ActionView::SyntaxErrorInTemplate (Encountered a syntax error while rendering template:
my profile.html.erb
<% if #users.image.present? %>
<%= image_tag #users.image %>
<% end %>
<strong><h1><%= #users.full_name %></h1></strong>
<% if user_signed_in? %>
<% if #user == current_user %>
<%= link_to"Edit Profile", edit_user_registration_path(#user) %>
<% if user_signed_in? && !#user? %>
<% if current_user.following?(#user) %>
<%= link_to"Unfollow", follows_path(user_id: #user.id), method: :delete %>
<% else %>
<%= link_to"Follow", follows_path(user_id: #user.id) %>
<% end %>
<% end %>
<% end %>
<% end %>
<div> <%= #users.posts.count %> Posts </div>
<p><%= #users.full_name %></p>
<p><%= #users.description %></p>
<p><%= link_to #users.website if #users.website.present? %></p>
<%= #posts.each do |post|%>
<%= image_tag post.image %>
<% end %>
<% if user_signed_in? && #user == current_user %>
<%= link_to"Edit Profile", edit_user_registration_path(#user) %>
<% if current_user.following?(#user) %>
<%= link_to"Unfollow", follows_path(user_id: #user.id), method: :delete %>
<% else %>
<%= link_to"Follow", follows_path(user_id: #user.id) %>
<% end %>
<% end %>
now it's ok :D
Seems like issue is here
<p><%= link_to #users.website if #users.website.present? %></p>
Change it to
<p><%= link_to 'User Website', #users.website if #users.website.present? %></p>
I have seen two mistakes, please correct them. first there is nothing #user? that is biggest error, another might not be problem but there is no space <%= link_to"Edit Profile" Please try following code I have changed things and reformat it properly.
<% if #users.image.present? %>
<%= image_tag #users.image %>
<% end %>
<strong><h1><%= #users.full_name %></h1></strong>
<% if user_signed_in? %>
<% if #user == current_user %>
<%= link_to "Edit Profile", edit_user_registration_path(#user) %>
<% if user_signed_in? && !#user %>
<% if current_user.following?(#user) %>
<%= link_to"Unfollow", follows_path(user_id: #user.id), method: :delete %>
<% else %>
<%= link_to"Follow", follows_path(user_id: #user.id) %>
<% end %>
<% end %>
<% end %>
<% end %>
<div> <%= #users.posts.count %> Posts </div>
<p><%= #users.full_name %></p>
<p><%= #users.description %></p>
<p><%= link_to #users.website if #users.website.present? %></p>
<%= #posts.each do |post|%>
<%= image_tag post.image %>
<% end %>

Rails use content_for and render the same layout twice

I am using a theme that has very specific layouts and I wanted to make a failsafe way to you rails forms.
I have a layout app/views/shared/forms/fields/_layout.html.erb
<div class="js-form-message mb-4">
<div class="js-focus-state input-group u-form">
<div class="input-group g-brd-primary--focus">
<%= yield(:field) %>
</div>
</div>
</div>
And I have two partials.
1-st partial: app/views/shared/forms/fields/_email.html.erb
<% form = locals[:form] %>
<% locals[:required] = locals[:required].nil? ? true : locals[:required] %>
<% locals[:placeholder] = locals[:placeholder] || t('forms.shared.email.placeholder') %>
<%= render layout: "shared/forms/fields/layout", locals: locals do %>
<% content_for(:field) do %>
<%= form.email_field :email,
placeholder: locals[:placeholder],
class: "form-control g-py-15 g-px-15",
"data-error-class"=>"u-has-error-v1-3",
"data-success-class"=>"u-has-success-v1-2",
"data-msg-email" => t('forms.shared.email.validate'),
"data-msg" => t('forms.shared.required'),
autofocus: locals[:autofocus],
required: locals[:required] %>
<% end %>
<% end %>
2-nd partial: app/views/shared/forms/fields/_login.html.erb
<% form = locals[:form] %>
<% locals[:required] = locals[:required].nil? ? true : locals[:required] %>
<% locals[:placeholder] = locals[:placeholder] || t('forms.shared.login.placeholder') %>
<%= render layout: "shared/forms/fields/layout", locals: locals do %>
<% content_for(:field) do %>
<%= form.email_field :login,
placeholder: locals[:placeholder],
class: "form-control g-py-15 g-px-15",
"data-error-class"=>"u-has-error-v1-3",
"data-success-class"=>"u-has-success-v1-2",
"data-msg" => t('forms.shared.required'),
autofocus: locals[:autofocus],
required: locals[:required] %>
<% end %>
<% end %>
And when I do this:
<%= render "shared/forms/fields/email", locals: {form: f} %>
<%= render "shared/forms/fields/login", locals: {form: f} %>
I get
Email Field
Email Field/Login Field
I found out that content_for 'appends' the block that you give it and then when I yield the whole block is returned.
The first time there is nothing in content_for(:field) and it appends to it Email Field. But the second time it does not clear its content and just appends Login Field to it.
I am thinking of adding additional complexity to layout.html.erb so just keeping it inline isn't an option.
Is there a way to tell to the layout only to yield the 'newest' value of content_for.
EDIT:
I wrote a method to flush after an yield, suggesting that the same key would be used again:
def yield_and_flush!(content_key)
view_flow.content.delete(content_key)
end
content_for has flush option to reset previous content:
<% content_for :field, flush: true do %>
new content here
<% end %>
The solution was this to write an yield_and_flush! method. I saw the solution here
def yield_and_flush!(content_key)
view_flow.content.delete(content_key)
end

Reduce code redundancy

I have a rails application which has some following code
<ul class="sortable grid row">
<% #videouploads.each do |video_upload| %>
<% if video_upload.category == 'モノナビ' && video_upload.priority == 1 %>
<%= render partial: 'adminrow', :locals => {:video_upload => video_upload } %>
<% end %>
<% end %>
</ul>
I have to write this code 10 times for video_upload.priority == 1 where priority changes from 1 to 10. How do I avoid code duplication or do I have what is the best solution ?
loop over the priorities
<% priorities = (1..10).to_a %>
<% priorities.each do |priority| %>
<ul class="sortable grid row">
<% #videouploads.each do |video_upload| %>
<% if video_upload.category == 'モノナビ' && video_upload.priority == priority %>
<%= render partial: 'adminrow', :locals => {:video_upload => video_upload } %>
<% end %>
<% end %>
</ul>
<% end %>
<% (1..10).each do |inc| %>
<ul class="sortable grid row">
<% #videouploads.each do |video_upload| %>
<% if video_upload.category == 'モノナビ' && video_upload.priority == inc %>
<%= render partial: 'adminrow', :locals => {:video_upload => video_upload } %>
<% end %>
<% end %>
</ul>
<% end %>
How about this ?

How to add a class to a select dropdown loop using ERB

I have the following loop to create a select dropdown using ERB. It is working correctly.
<%= f.select(:player_id) do %>
<% #players.each do |p| %>
<%= content_tag(:option, "#{p.first_name} #{p.last_name}", value: p.id) %>
<% end %>
<% end %>
My question is how do I add a class to the select element?
I have tried the following:
<%= f.select(:player_id), class: "form-control" do %>
<% #players.each do |p| %>
<%= content_tag(:option, "#{p.first_name} #{p.last_name}", value: p.id) %>
<% end %>
<% end %>
and
<%= f.select(:player_id), { class: "form-control" } do %>
<% #players.each do |p| %>
<%= content_tag(:option, "#{p.first_name} #{p.last_name}", value: p.id) %>
<% end %>
<% end %>
I have seen questions similar to this, but none that use a loop like the example above.
This should work for you.
<%= f.select :player_id, options_for_select( #players.collect { |player| ["#{player.first_name} #{player.last_name}", player.id] } ), class: 'form-control' %>
This is what I ended up doing:
<%= f.select :player_id, options_for_select( #players.collect { |player| ["#{player.first_name} #{player.last_name}", player.id] } ), {}, { class: 'form-control' } %>
I think problem with your code is f.select(:player_id).
You are calling the select method with only one parameter :player_id. So you can pass other options like this.
<%= f.select :player_id, class: "form-control" do %>
<% #players.each do |p| %>
<%= content_tag(:option, "#{p.first_name} #{p.last_name}", value: p.id) %>
<% end %>
<% end %>

Import html to rails method (in helper.rb)

I need piece of code for couple of times, and to follow DRY method (don't repeat yourself) i want to escape using this piece and retyping it for 5 times or more. So I want to define method what will contain both ruby and html, and ruby in html and js to, code. But I have problems with realization.
My html.erb look like this:
<% div_count = 1 %>
<div>
<% for post in #posts %>
<div class="post-on-main-page-<%= div_count %>"
id="js-count-<%= div_count_for_js %>">
<script>
$("#js-count-<%= div_count_for_js %>").click(function(){
window.location.href = "<%= post_url(post) %>";
});
</script>
<%= image_tag(post.picture.url) %>
<span><h5><%= post.theme %></h5></span>
</div>
<% end %>
<% div_count += 1 %>
<% if div_count == 4 %>
<% div_count = 1 %>
<% end %>
</div>
And I want create method, I think in application_helper.rb will do with this piece of code. What will look something like that:
def method_name(parameter)
<% div_count = 1 %>
<div>
<% for post in parameter %>
<div class="post-on-main-page-<%= div_count %>"
id="js-count-<%= div_count_for_js %>">
<script>
$("#js-count-<%= div_count_for_js %>").click(function(){
window.location.href = "<%= post_url(post) %>";
});
</script>
<%= image_tag(post.picture.url) %>
<span><h5><%= post.theme %></h5></span>
</div>
<% end %>
<% div_count += 1 %>
<% if div_count == 4 %>
<% div_count = 1 %>
<% end %>
</div>
end
The result what I want for html.erb
<%= method_name(#posts)%>
How can I make this to work?
You can move this code to some html. And when you want to use it, you just call render method.
<%= render 'html_file' %>