Iterative display of objects in Rails - ruby-on-rails

I find that when I iteratively render a collection of objects, say, comments, rails also lists the addresses of the objects. For example, my view may contain the following:
<h3>Comments</h3>
<% if #blogpost.comments.any? %>
<%= #blogpost.comments.each do |comment| %>
<%= render :partial => "comment", :locals => {:comment => comment} %>
<% end %>
<% end %>
The view often shows this:
<h3>Comments</h3>
<p>comment #2</p>
<p class="post-info"> >> Example User, about 1 hour ago. </p>
<p>this is user 1's comment on user 5's article</p>
<p class="post-info"> >> Example User, 2 days ago. </p>
#<Comment:0xb6f91968>#<Comment:0xb6f9016c>
As you can see, there are a couple of address listings for the objects, which I would prefer not to have in the view. Is there a way to suppress this output? Thanks in advance for your time!

remove = from <%= #blogpost.comments.each do |comment| %>
when we add = in <% %> rails will execute erb code and render the output in html.

Also, you don't really need all of this code.
You can left only these two lines to render 'comment' partial for #blogpost.comments collection:
<h3>Comments</h3>
<%= render #blogpost.comments %>
and Rails will do the trick.
http://api.rubyonrails.org/classes/ActionView/Partials.html

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 <%= %>

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.

Putting a line break between posts in rails

I'm working with rails and I have gotten a bunch of posts set up. However, I am trying to put a linebreak or some whitespace in between each post. I've got all the articles to display using <%= render #articles %> onto the index page but I am unsure how to proceed to add whitespace. Any help would be greatly appreciated! Thanks!
You should loop trough the articles and add some custom HTML CSS to them.
<% #articles.each do |article| %>
<%= article %>
<%= link_to article.number, article, {:class => "artikel"} %>
<br />
<% end %>
Or add them to a proper html tag like p
<% #articles.each do |article| %>
<p><%= article %></p>
<% end %>
FYI you can also use a second partial that will be rendered by Rails between each instance of your main partial, this can be interesting depending of the complexity of your layout, but probably overkill for just a <br /> ;-)
<%= render #articles, :spacer_template => "article_spacer" %>

How do I run an array through an IF statement in rails?

I am creating an application that highlights user messages from a stream based on whether or not the user has been 'vouched'. It works fine if it's setup for a single author. For example
controller: #vouch = Vouch.last.vouched_user_nickname
view:
<% Twitter::Search.new(params[:id]).each do |tweet| %>
<li>
<%= image_tag tweet.profile_image_url %>
<% if #vouch.include? tweet.from_user %> <div class="flit_message_containerh">
<u> <%= tweet.from_user %></u> <%= linkup_mentions(auto_link(h tweet.text)) %>
<div class="time_ago">
<%= link_to distance_of_time_in_words_to_now(tweet.created_at) , tweet %>
<% else %> <div class="flit_message_container">
<u> <%= tweet.from_user %></u>
<%= linkup_mentions(auto_link(h tweet.text)) %>
<div class="time_ago">
<%= link_to distance_of_time_in_words_to_now(tweet.created_at) , tweet %>
<% end %>
But I'm having trouble doing it for multiple user nicknames.
#vouch = Vouch.find(:all,
:select => "vouched_user_nickname",
:group => 'vouched_user_nickname'
)
Any ideas would be greatly appreciated. I'm a rails noob.
Assuming there isn't a relation between your Vouch model and the Twitter source (I haven't used that gem/plugin yet so I don't know), one solution is to pull all the Twitter entries you want and all the vouches in the controller and do the check in the view.
controller:
#tweets = Twitter::Search.new(params[:id])
#vouches = Vouch.find(:all)
view:
<% #tweets.each do |tweet| %>
<div class="flit_message_container<%=
#vouches.any? { |v| v.vouched_user_nickname == tweet.from_user } ? "h" : ""
%>">
...
</div>
<% end %>
#vouch = Vouch.find_by_vouched_user_nickname(:all, ["nickname1","nickname2"])
Your problem seems to be that you are not looping through the array, so how can it decide if certain elements meet the criteria you set?
Example, in your view:
<% for vouch in #vouch do %>
<% if vouch.include? tweet.from_user %>
<div class="flit_message_containerh">
<u> <%= tweet.from_user %></u> <%= linkup_mentions(auto_link(h tweet.text)) %>
<div class="time_ago">
<%= link_to distance_of_time_in_words_to_now(tweet.created_at) , tweet %>
<% else %> <div class="flit_message_container">
<u> <%= tweet.from_user %></u>
<%= linkup_mentions(auto_link(h tweet.text)) %>
<div class="time_ago">
<%= link_to distance_of_time_in_words_to_now(tweet.created_at) , tweet %>
<% end %>
<% end %>
I see several problems.
The first one is this:
#vouch = Vouch.last.vouched_user_nickname
You are using a variable called #vouch to store a user nickname. That is counterintuitive and will confuse other people reading your code (like myself). Use something like this instead:
#vouch = Vouch.last #on the controller
#vouch.vouched_used_nickname #on the view
This ... eum ... "exotic" naming convention helps confusing yourself when you try to do the "multiple" example:
#vouch = Vouch.find(:all,
:select => "vouched_user_nickname",
:group => 'vouched_user_nickname')
Activerecord's find(:all, ...) will allways return an array of activerecord objects (or an empty array). You seem to be expecting an array of strings. You will allways get Vouches if you do Vouch.find.
The :select part just limits the amount of information these vouches have (they only come with vouched_user_nickname populated. The rest, including their id, is empty, because it is not read from the database).
If you want to have an array of user nicknames you can do it like this:
# note the names. #vouchers in plural, and #nicknames for the user names
#vouchers = Vouch.find(:all, :select => "vouched_user_nickname",
:group => 'vouched_user_nickname')
#nicknames = #vouchers.collect{|v| v.vouched_user_nickname}
Is your problem that you don't know the correct controller code to write to find the #vouch array? Or is it that you don't know what to do with the array once you get it?
view: <% if #vouch.include? tweet.from_user %>
.include? is a method you can call on either a single object or an array of objects if tweet.from_user has an object that is also included in the #vouch array to get the #vouch array in your controller you should:

What's the cleanest way to add a class attribute to an html element in a view in rails

I'm writing some Rails code for a partial view, and I want it to only show a comment field if somebody is already logged onto a site here.
If the page is viewed by someone who isn't a member of the site yet, the shared/comment_not_logged_in fragment should be passed in.
However, I'm totally stumped as to why I can't run the same check to decide if the page should add the class attribute "missing_your_voice" to the enclosing div element here:
<li class="user_submission_form bubble comment_form <% "missing_your_voice" if not current_user %>">
<% if current_user %>
<%= image_tag(current_user.avatar(:comment), :class => "profile_pic") %>
<% form_for [parent, Comment.new] do |f| %>
<%= render "comments/form", :f => f %>
<% end %>
<% else %>
<%= render :partial => 'shared/comment_not_logged_in' %>
<% end %>
</li>
The same idiom, "missing_your_voice" if not current_user returns the string in irb, and also in the console debugger.
What am I doing wrong here?
You forgot an =. Replace <% by <%=, so that you get:
<%= "missing_your_voice" if not current_user %>
Remember that <% ... %> will only run Ruby code, but not display anything. Using <%= ... %> will run the code and display the result of the expression.
As molf already pointed out, there's a missing = on your view.
It should be <%=.
Other than that, be sure to make your controller method available to your view by calling helper_method in your controller.
Take a look on the documentation if needed.

Resources