Rails - conditional display of html block - ruby-on-rails

On my views I use 1 form that includes a block that renders comments. I do not want to run it when creating a new record. So, I tried conditions like so...
<% unless #annotation_id.nil? %>
<hr>
<div class="row">
<div class="col-md-8">
<h4>Comments</h4>
<%= render #annotation.comments %>
</div>
<div class="col-md-4">
<%= render 'comments/form' %>
</div>
</div>
<% end %>
This however results in never displaying the block - also when the annotation record exists. What am I doing wrong?

You don't show that you have actually set #annotation_id to something.
A simpler way might be to use the .new_record? method instead, like:
<% unless #annotation.new_record? %>
...
<% end %>

use if #annotation.persisted? or unless #annotation.new_record?

Related

Strange output from rails each do

Rails each do method is acting strangely and I do not know why.
controller
def index
#fabric_guides = FabricGuide.with_attached_image.all.order(:name)
end
index.html.erb
<div class="guide-items">
<%= #fabric_guides.each do |fabric| %>
<div class="guide-container">
<%= link_to fabric_guide_path(slug: fabric.slug) do %>
<%= image_tag fabric.image if fabric.image.attached? %>
<% end %>
<div class="guide-info">
<p class="g-name">
<%= link_to fabric.name,
fabric_guide_path(slug: fabric.slug) %>
</p>
</div>
</div>
<% end %>
</div>
I have two FabricGuide records so I expect two "guide-container" but I get three. Or more precisely I get two guide containers and a third block of text containing all the content from the last FabricGuide record.
I have almost an identical setup for articles and have never encountered this problem. I'd happily share more information if needed. Thank you!
Please remove = equal sign from your each loop of view code
like below :-
<% #fabric_guides.each do |fabric| %>
...
...
<% end %>
you have used this <%= #fabric_guides.each do |fabric| %> in your view that's why it shows all record in DOM.
The expression for erb tags is <% %>
now if we want to print that tag too then we apply <%= %>

Rendering only authorized (Devise) user data in Rails without excess empty space

I am trying to create a todo app that will allow the user to create lists and then "todo" items under each list. However, I want each user to only be able to see his or her lists. While I've been able to partially solve it using the current_user helper, the index page shows empty space where the other users lists are hidden.
Below please find the code for the index.html.erb page inside my todo_lists views.
<% #todo_lists.each do |todo_list| %>
<div class="index_row clearfix">
<% if todo_list.user == current_user %>
<h2 class="todo_list_title"><%= link_to todo_list.title, todo_list %></h2>
<p class="todo_list_sub_title"><%= todo_list.description %></p>
<p><%= todo_list.user.first_name %></p>
<% end %>
</div>
<% end %>
<div class="links">
<%= link_to "New Todo List", new_todo_list_path %>
</div>
Here's my repo on Github, in case you need to see more of the code: https://github.com/jramoscolon/todo
Is there a way to hide these empty spaces, as well as the non-matching todo items?
Given your current view code, you are indiscriminately emitting <div class="index_row clearfix"> elements, even when the todo_list.user does not match the current_user. Simply move the whole<div> outside the current_user check, like so:
<% #todo_lists.each do |todo_list| %>
<% if todo_list.user == current_user %>
<div class="index_row clearfix">
<h2 class="todo_list_title"><%= link_to todo_list.title, todo_list %></h2>
<p class="todo_list_sub_title"><%= todo_list.description %></p>
<p><%= todo_list.user.first_name %></p>
</div>
<% end %>
<% end %>
This way, all of those empty <div> elements aren't included on the page. This should clean up all that empty space.
If your index view is user specific than the instance variable you want should be user specific as well.
Instead of #todo_lists = ToDoList.all
Use the current_user.todo_lists functionality supplied by your has_many/belongs to

HTML Snippets that repeat in the Rails views

I am using a bootstrapping framework, that has the following snippet, which I use a lot:
<div class="panel panel-default">
<div class="panel-heading">...</div>
<div class="panel-body">
...
</div>
</div>
(The snippet will be actually bigger, but I want to start small)
So I thought I would build a partial and use it, something like this:
Partial
<div class="panel panel-default">
<div class="panel-heading"><%= title %></div>
<div class="panel-body">
<%= yield %>
</div>
</div>
Use example
<%= render partial: "panel", locals: { title: "Hello" } do %>
Testing
<% end %>
But this apparently is not working. I get the following error:
'nil' is not an ActiveModel-compatible object. It must implement :to_partial_path.
Am I doing something wrong here? Did I understood partials wrong?
In order for yield to work I think you need to use render :layout instead of/in addition to :partial:
<%= render layout: "panel", locals: { title: "Hello" } do %>
Testing
<% end %>
Have a read of the PartialRenderer examples for more information

Rails: Using Yield, Calling Multiple View Pages

Problem: How Do You Render Multiple View Pages From Different Controllers?
In my views/layouts/application.html.erb, I call views/posts/index.html.erb with the yield method.
<div class='span10'>
<%= yield %>
</div>
On top of it, I wanted to call views/good_posts/index.html.erb with yield. So in that particular index file, I wrap around all the code with content_for method.
<%= content_for :good_post do %> all my content in good_post/index.html.erb <% end %>
I go back to application.html.erb, I tried to call the index file of good_post with yield method.
<div class='span10'>
<%= yield :good_post %>
</div>
<div class='span10'>
<%= yield %>
</div>
I thought this would result in good_post/index to be rendered on top of post/index, but it did not work; only post/index was correctly rendered as before. Could someone explain why this is, and tell me the correct way to approach this problem? I appreciate your help!
You should, as #cdesrosiers said, rename the index.html.erb file in good_posts to _index.html.erb. Then you can render this view in your application like this:
<div class='span10'>
<%= render 'good_posts/index' %>
<%= yield :good_post %>
</div>
<div class='span10'>
<%= yield %>
</div>
Personally, I would change the index.html.erb file in good_posts folder to _good_posts.html.erb file in app/views/posts folder. Your code will have better meaning, and you can know where to find it after, because it relates to posts. So, if you change this, use this code:
<div class='span10'>
<%= render 'posts/good_posts' %=
<%= yield :good_post %>
</div>
<div class='span10'>
<%= yield %>
</div>
Another you should change is content_for :good_post -> content_for :good_posts , because good posts maybe have many posts, so you should use post in pluralize.

Rails Views: How do you pass a variable to a partial layout?

In one of my views I apply a layout to a block of code:
# In app/views/sessions/new.html.erb
<% render :layout => 'home/shadow_box' do %>
#... code for sign in form here
<% end %>
The layout is a div that has png shadows on all four sides.
Since I use this layout all over my site, I want to pass a variable to the layout that specifies the width of the shadowed div. I tried using content for in the code block:
# In app/views/sessions/new.html.erb
<% render :layout => 'home/shadow_box' do %>
<% content_for :box_width %>640<% end %>
#... code for sign in form here
<% end %>
# In app/views/home/_shadow_box.html.erb
<div class="shadow-one" style="width:<%= yield :box_width %>;">
<div class="corner-a"></div>
<div class="corner-b"></div>
<div class="shadow-two">
<div class="shadow-three">
<div class="shadow-four">
<%= yield %>
</div>
</div>
</div>
</div>
This didn't work and instead resulted in a double render of the entire code block.
What's the best way to tackle this problem?
Figured it out.
From the API: "You can also yield multiple times in one layout and use block arguments to differentiate the sections."
Solution:
# In app/views/sessions/new.html.erb
<% render :layout => 'home/shadow_box' do | section | %>
<%- case section when :box_width -%>
#width goes here. I.e., 640px
<%- when :content -%>
#code block goes here
<% end -%>
<% end %>
#In app/views/home/_shadow_box.html.erb
<div class="shadow-one" style="width:<%= yield :box_width %>;">
<div class="corner-a"></div>
<div class="corner-b"></div>
<div class="shadow-two">
<div class="shadow-three">
<div class="shadow-four">
<%= yield :content %>
</div>
</div>
</div>
</div>
First you need to know the difference between layouts and partials. Partials are generally from the view but can also be used from the controller if you are using ajax. Layouts are almost always used in the controller.
First create a file in a shared folder such as application/ and in this folder put a file call it whatever you want but it will contain the material that you want to include all over your site. Then when you pass a variable to a partial it's called in the partial as a local variable. Also with partials you don't need to say render :partial => you just put render 'application/some_file'
So from the view you want this:
<%= render 'application/your_file', :div_size => '600' %>
And then from the partial in the folder such as application/your_file.html.erb do this:
<div style="width:<%= div_width %>px;">
content
</div>

Resources