I'm building a feed of images, videos, and text-posts using the same model.
For an image post I have an image column, for text a body field, and for videos a url. I have separate partials for each type of post. Right now I'm looping through the posts like this:
<% #posts.each do |post| %>
<% if post.image.present? %>
<%= render 'image_post' %>
<% elsif post.body.present? %>
<%= render 'text_post' %>
<% else %>
<%= render 'video_post' %>
<% end %>
<% end %>
It starts to get messy if I add any more types of posts. Is there a better way to do this?
Also, say I wanted to loop through just the video-posts. Can I loop though posts only with video_url present instead of doing this?
<% #posts.each do |post| %>
<% if post.video_url.present? %>
<%= render 'video_post' %>
<% end %>
<% end %>
you can add a mothod to you model to return the type of post
def type
return "image" if image.present?
return "text" if body.present?
return "video"
end
In your view
<% #posts.each do |post| %>
<%= render "#{post.type}_post" %>
<% end %>
Related
I have a Posts Model, and a Projects Model. I want to render both of these on one index page and order them by created_at DESC. How can I do this? Thanks in advance...
Separately?
<% Post.order('created_at DESC').each do |post| %>
#do things
<% end %>
<% Project.order('created_at DESC').each do |project| %>
#do things
<% end %>
Together?
<% (Post.all + Project.all).sort_by{|item| -item.created_at}.each do |item| %>
<% if item.is_a? Post %>
<%= render 'post_partial', post: item %>
<% elsif item.is_a? Project %>
<%= render 'project_partial', project: item %>
<% end %>
<% end %>
Then create a partial for both objects, and use your attributes as needed!
It is straightforward enough to display only the comments by people the user hasn't blocked:
<% post.comments.each do |comment| %>
<% unless user.blocking?(comment.user) %>
<%= render comment %>
<% end %>
<% end %>
It is also straightforward to display the comments in ascending order (the ascending scope is defined):
<% if post.comments.any? %>
<%= render post.comments.ascending %>
<% end %>
But how do you do both of these things at once in a succinct railsy way?
Just order the comments before iterating over them with each:
<% post.comments.ascending.each do |comment| %>
<% unless user.blocking?(comment.user) %>
<%= render comment %>
<% end %>
<% end %>
You can also combine the unless with your output:
<% post.comments.ascending.each do |comment| %>
<%= render comment unless user.blocking?(comment.user) %>
<% end %>
By the way, ascending isn't documented anywhere - in what context are you using it? Do you have a scope defined for it?
I created two scaffolds: announce_sections and announcements. The announce_sections are the types of announcements there are (i.e. games, tryouts, etc) and when I create an announcement I specify what type of announce_sections it is. I'm trying to display it so that each announce_section is viewed, with each announcement and its information under the announce_section. This is what I came up with:
<% #announce_sections.each do |announce_section| %>
<%= announce_section.name %>
<% #announcements.each do |announcement| %>
<%= announcement.announcement_title %>
<%= announcement.information %>
<%= announcement.additional_information %>
<%= announcement.type %>
<% end %>
<% end %>
However, this code only displays the announce_sections with the all announcements under it. The announcements don't get separated into their respective announce_sections. How do I change it so that it does?
<% #announce_sections.each do |announce_section| %>
<%= announce_section.name %>
<% #announcements.where(type: announce_section).each do |announcement| %>
<%= announcement.announcement_title %>
<%= announcement.information %>
<%= announcement.additional_information %>
<%= announcement.type %>
<% end %>
<% end %>
Use the name of the field you are using to assign the announcement type instead of 'type'
There are many ways to solve this, but one simple one is to build a hash where the key is the type of announcement_section and the value is an array (or Set) of the announcement. One way to build that hash is to use the Hash.new {|hash, key| ... } form of the constructor.
#hash = Hash.new {|hash, section| hash[section] = Array.new }
#announcements.each do |a|
# for each announcment append it to the array under the hash
#hash[a.section] << a
end
And then, in the view
<% #hash.keys.each do |section| %>
<%= section %>
<% #hash[section].each do |announcement| %>
<%= announcement.announcement_title %>
<%= announcement.information %>
<%= announcement.additional_information %>
<%= announcement.type %>
<% end %>
<% end %>
I have a model Post with :mark, :text
I have a list with my post
<% #posts.each do |p| %>
# todo
<% if p.mark? %>
<%= p.mark %> <%= sweet_thing(p.text) %>
<% else %>
<%= sweet_thing(p.text) %>
<% end %>
<% end %>
I need to show p.mark name instead #todo where p.mark first time appearance.
Final txt example:
Audi
Audi, text-text-text-text.
Audi, text-text-text-text.
Audi, text-text-text-text.
Ford
Ford, text-text-text-text.
Ford, text-text-text-text.
Ford, text-text-text-text.
Ford, text-text-text-text.
UPDATE
My txt render in controller
def txt_receiver
#posts = Post.where("created_at >= ?", 7.days.ago.utc).find(:all, order: "mark, LOWER(post)")
render "txt_for_newspapper", formats: ["text"]
end
An obvious solution is to keep track of seen marks.
<% seen_marks = {} %>
<% #posts.each do |p| %>
<% unless seen_marks[p.mark] %>
<%= p.mark %>
<% seen_marks[p.mark] = true %>
<% end %>
# rest of your code
<% end %>
A better solution (I think) involves grouping posts by their mark and then outputting in groups. But I'm not sure whether it will match your logic regarding missing marks.
<% #posts.group_by(&:mark).each do |mark, posts| %>
<%= mark %>
<% posts.each do |p| %>
<%= p.mark if mark %> <%= sweet_thing(p.text) %>
<% end %>
<% end %>
I have a view like this,
<% count = 1 %>
<% for voting in #voting %>
<% if voting.question_id.eql?(count) %>
<%= radio_button( count, voting.vote_count, :radio_id => voting.nominees ) %>
<%= voting.nominees %>
<% end %>
<% if voting.nominees.eql?(radio_id) %>
<% voting.update_attribute('vote_count', voting.vote_count+1 ) %>
<% end %>
<% count += 1 %>
<% end %>
how can i compare the selected nominees with the existing one.
any help on this would be very useful...
Some models and associations would be handy here. I suspect options_from_collection_for_select will be your best friend. Also look at increment.