Printing string inside nested hash - Ruby - ruby-on-rails

I have been trying to learn the ropes of ruby for a Rails project that I picked up. I have C++ experience but am still learning my way around Ruby, so I will apologize now for not understanding Ruby and its nuances.
I have a hash that has elements containing another hash of strings...
def directors = {
gm: { pos: "General Manager", email: "123#abc.com" },
prod: { pos: "Production Director", email: "456#def.com" },
support: { pos: "Support Director", email: "789#xyz.com" }
}
end
Within html I am able to run ruby code to access and output each respective string individually...
<%= directors[:gm][:pos] %>
<%= directors[:gm][:email] %>
<%= directors[:prod][:pos] %>
<%= directors[:prod][:email] %>
<%= directors[:support][:pos] %>
<%= directors[:support][:email] %>
This is a tedious and manual way to obtain and output every single element. I am attempting to write this in a more concise manner and in a way so that it will always display every element regardless of knowing how many elements are in each. I can write directors.each to call each element inside directors, but I need to again access each element inside of each director element. This is the best code I could come up with, but is not syntactically correct.
<% directors.each do |director| %>
<% "#{director}" do |info| %>
<%= dirs[:"#{director}"][:"#{info}"] %>
<% end %>
<% end %>

If you just want to display the nested hash, you can do so like this:
<% directors.each do |_internal_name, details| %>
Position: <%= details[:pos] %>
Email: <%= details[:email] %>
<% end %>

Related

How to handle the checkbox with two array and if in one array user on-click the checkbox that should append in second array

#complete[] and #incomplete[] are two array then I need to used with these array with checkbox complete array is by default true and incomplete by default false .
<%= form_with(model: #task, local: true) do |form| %>
<% #complete = Array.new %>
<% #incomplete = Array.new %>
<% #tasks.each do |task| %>
<% if task.complete != false then %>
<% #complete << task.name %>
<% else %>
<% #incomplete << task.name %>
<% end %>
<% end %>
<!-- complete task -->
<%= #complete %>
<!-- incomplete task -->
<%= #incomplete %><br>
<% #complete.each do |i| %><div id = "task_check">
<%= form.check_boX "#incomplete[]", incomplete.id %>
<%= form.check_box "chkbox_ary[#{i}]" , {checked:true} %>
<%= form.submit "update"%>
<%= content_tag(:strike, i)%>
<br></div>
<% end %>
<br> <hr>
<script>
<% #incomplete.each do |i| %>
<%= form.check_box "chkbox_ary[#{i}]" %>
<%= form.submit "update"%>
<%= i %><br>
<% end %>
<% end %>
If I check the box as false in complete then it should append to array called complete and if I check the box true in incomplete then it should append to second array called complete.
if I may, I'd like to point out some stylistic issues in your code first:
it is unusual to compare with false, i.e., if task.complete != false should be just if task.complete this works thanks to the concept of Truthiness in Ruby
you can just leave off the then in an if-conditional, that's what most Ruby developers do, i.e., if task.complete then can just be if task.complete
view templates (.erb files) should contain as little logic as possible, i.e., extract the creation of the #incomplete and #complete arrays into your controller or some other place
Ruby Enumerable has many methods to make common work easier, for instance splitting a collection into two collections can be done with partition, i.e., you can do #complete, #incomplete = #tasks.partition(&:complete) to populate the complete and incomplete arrays (&:complete is a shorthand for { |task| task.complete }, google Ruby symbol to proc if you want to know more about it)
I'm not sure I understand your question as it is. At the time the complete and incomplete arrays exist no user interaction takes place. I.e., nobody can click anything. When the HTML is rendered, no arrays exist anymore.
So there's two ways I can interpret your question:
You wish to move the DOM elements around => you need to use JavaScript for that
You wish to partition the checkboxes when the form is submitted => you need to show us the code in your controller that handles the form-submit for us to help you out
Which is it?
PS: I know this isn't an answer right now, but I could not write this as a comment since it's too long and a comment would have been illegible.

Comments from post not displaying correctly in rails

Been trying to set up a regular blog in Ruby on Rails, and finally got the comment system to work within a post. However, when I loop through each comment and try to output the comment's title it displays this,
awef [#<Comment id: 6, title: "awef", link: nil, campaign_id: 5, user_id: 1, created_at: "2015-09-24 09:46:43", updated_at: "2015-09-24 09:46:43">]
Instead of just the title. How can I fix this?
The loop in your view should be something like this:
<% #blog.comments.each do |f| %>
<%= f.title %>
<% end %>
Please check you are using the right angular parenthesis (<%= %>) and not placing p puts or inspect commands inside them.
Edit:
Now that you show use the code, the problem is in the first angular parenthesis: should be <% not <%=. The first is for the logic, the latter to output erb code.
<% #blog.comments.each do |f| %> # remove "="
<%= f.title %>
<% end %>
<% ... %>: Executes the ruby code within the brackets
<%= ...%>: Executes the ruby code and show the executing result in webpage
Classic mistake, it's because you're using <%= ERB output tags for the .each loop. You can view more information on how to write correct ERB here.
You need to replace your <%= output tags with standard ERB tags <%:
<% #blog.comments.each do |f| %>
I was stung by that one myself when I was starting out.
The problem you have is probably the = in your each statement.
Try to use this:
<% #blog.comments.each do |f| %>
<%= f.title %>
<% end %>
Notice the removed = at <% #blog.comments.each do |f| %>
The reason is as the <%= %> always prints while <% %> only executes the code.

Fixnum.times { image_tag('path_to_file') } returns the fixnum

I was trying to refactor my erb code for rating stars into one line and came across this, is it possible to achieve the results another way?
So currently it's like this
<% rating.times do %>
<%= image_tag 'rating_star.png' %>
<% end %>
Ideally I'd like to reduce this to
<%= rating.times { image_tag 'rating_star.png' } %>
This returns the value of rating (0, 1, 2, 3, 4 or 5), if I change <%= to <% nothing is rendered. Is there any way to do this?
You can use concat:
<% rating.times { concat image_tag('rating_star.png') } %>
But <%= ... %> within a loop is cleaner IMO.
You need #map to return an array of all image_tags you wish.
Then #join the result to get a string.
Lastly, you need to tell this string is valid html with #html_safe.
<%= rating.times.map{ image_tag 'rating_star.png' }.join.html_safe %>
The difference between <% %> and <%= %> is that the former is simply evaluated, but with the latter the result is rendered. You have two things going on in your code snippet: the control part (the loop), and the rendering part (the image tag). Since you want only the image tag part rendered, you want to surround only that code with <=% %>, and the rest with <% %>.
So while this would work:
<%= rating.times { %> <%= image_tag 'rating_star.png' %> <% } %>
I find it much less readable than the 3-line version.

Rails instance variable join

This is so simple but it's been ages since I needed this.
I have the following code
<% #miniature.minisets.each do |miniset| %>
<%= link_to miniset.name, miniset %>
<% end %>
It outputs Minisetname Minisetname Minisetname etc
I want it to output Minisetname, Minisetname, Minisetname with commas.
I've tried to include .join(", ") but can't find the right place to put it. Do I also need to use .map instead of .each?
Ignominy.
Here's one way that ought to work:
<%= #miniature.minisets.map { |miniset| link_to miniset.name, miniset }.join(", ").html_safe %>

Add interval text if previous element exists

Using Rails 3. This is a front-end design question.
Goal:
Contact | Email | URL
show.html.erb:
<% if !#shop.contact.blank? %>
<%= #shop.contact %>
<% end %>
<% if !#shop.email.blank? %>
<%= #shop.email %>
<% end %>
<% if !#shop.url.blank? %>
<%= link_to #shop.url, #shop.url, :target => "_blank" %>
<% end %>
How do I put in | only when the previous and after element has values? At current stage, if there is no value, nothing is output.
Many thanks.
<% url = link_to(#shop.url, #shop.url, :target => "_blank") if #shop.url.present? %>
<%= [#shop.contact, #shop.email, url].select(&:present?).join(" | ") %>
This creates an array of all your elements, selects those which have a value (as present? is the opposite of blank?) and then joins each element of the remaining array by putting a pipe between them.
That said, if you have more complex logic, you should probably create a helper method. The ERB templates are not a good place for complex logic. This above is bordering acceptable.

Resources