I am trying to get a loop to post videos grouped by each day by created_at.
For example:
December 5, 2012 -
Video 9
Video 8
Video 7
December 4, 2012 -
Video 6
Video 5
December 3, 2012 -
Video 4
Video 3
Video 2
Video 1
videos_controller:
def index
#title = 'Hip Hop Videos, Breaking News, Videos, And Funny Shxt | HOTDROPHIPHOP'
#description = ''
#videos = Video.all
#days = Video.where(:created_at == Time.today )
end
View file:
<% #days.each do |day| %>
<div class="video-date">December 4, 2012</div>
<% #videos.each do |video| %>
<% end %>
<% end %>
I also need to get that div to show that day's date as well.
I searched around and couldn't find a solution and tried the group_by (which seemed the cleanest) but couldn't get it to work. I am a bit rusty on my Rails as I haven't touched it for months.
You can do this:
#videos = Video.where(Video.arel_table[:created_at].gteq(some_date_value))
#video_days = #videos.group_by {|video| video.created_at.to_date }
Where #video_days will be a hash in the form of {some_date_value: [{video1}, {video2}, etc], next_date_value: [{video3}, {video4}, etc], etc...}.
Since you are calling .to_date on the created_at field, it will drop all of the time information, effectively grouping everything by day.
You can loop through it like:
<% #video_days.each do |day, videos| %>
<%= day.strftime("some format") %>
<% videos.each do |video| %>
<%= #output videos how you see fit %>
<% end %>
<% end %>
The best way is to use the gem Groupdate
e.g User.group_by_day(:created_at).count
Allow you to order by day, week, hour
First of all it makes no sense to call only videos from today and then run through all videos.
I would try it this way:
Controller
#videos = Video.all(:conditions => ["created_at >= ?", Date.today.at_beginning_of_month])
View
<% Date.today.at_beginning_of_month.upto(Date.today).each do |date| %>
<%= date %>: <%= #videos.select{|u| u.created_at == date }.title %>
<% end %>
It should give you a Video list with "Date: Video Title" for the actual month.
Assumed you are using mysql and video has attribute title
I am posting the following code to help you to grasp the logic ( Surely it need re-factoring )
Controller
#videos = {}
videos = Video.order("DATE(created_at) DESC, title ASC").select("DATE(created_at) as created_at, title, id" )
videos.collect{|x| #videos[x.created_at.to_s] = #videos[x.created_at.to_s] ? #videos[x.created_at.to_s] << x.title : [x.title] }
view
<% #videos.each do |posted_date, videos| %>
<div class="video-date"><%= Date.parse(posted_date.to_s).strftime("%b %d, %Y") %> </div>
<%= videos.join(", ") %>
<% end %>
Related
I'm looping through an array of records like this:
#products = Product.where(category_id: #categories).order(updated_at: :desc)
<% #products.each do |product| %>
<%= #product.title %>
<%= #product.price%>
<% end %>
And now I wan to to mark the newest records as new releases:
<% #products.each do |product| %>
<% if product.created_at <= product.created_at + 2.days %>
New release
<% end %>
<%= #product.title %>
<%= #product.price%>
<% end %>
But instead of going through each product and marking which ones is new (according to the if condition I have), it just takes the first record which returns true to the if condition and marks all of the products as new.
Any idea why this is happening and how I can fix this?
Your logic is incorrect - this line:
if product.created_at <= product.created_at + 2.days
will always be true (you're comparing a date with itself), so everything will always be marked as a new product.
Did you mean to compare the created_at date with the current date instead? If you wanted to check if a product created less than two days ago, use product.created_at >= 2.days.ago.
I'm fairly new to rails, and working on a application that would display daily submissions. I'm now trying to display posts for every day. So I did a few things:
Set up the controller instance variable to a single #submissions, which takes the 'num_days_ago' input:
#num_days_ago = 1
#submissions = Submission.daily(#num_days_ago).paginate(page: params[:page], per_page: 10).order('rank DESC')
Set up the scope to be responsive to the num_days_ago input:
scope :daily, -> (num) { where( created_at: (num.days.ago.beginning_of_day..num.days.ago.end_of_day)) }
Added some helper methods to handle the dates in the views:
module WelcomeHelper
def the_date(num_days)
date = num_days.days.ago.to_date
date.to_formatted_s(:long_ordinal) end
def num_days_since_first_day
(Date.today - (Submission.last.created_at).to_date ).to_i end
end
Created a loop in the view to make it display all daily posts (I will add pagination and infinite scroll later):
<div class="container">
<% (0..num_days_since_first_day).each do |num| %>
<h3><%= the_date(num) %></h3>
<ul>
<%= render #submissions %>
</ul>
<div id="show_more">
<%= link_to 'Show More', welcome_index_path(page: 2), class: "show_more_link", remote: true %>
</div>
<% #num_days_ago +=1 %>
<% end %>
</div>
Also, here is the submissions partial being displayed in the Index view:
<li>
<%= render partial: 'votes/voter', locals: { submission: submission } %>
<%= submission.title %></br>
<%= submission.description %> | $<%= submission.price %> | <b><%= submission.merchant.name %></b> | Submitted by: <%= submission.user.name %>
</li>
</br>
So now, the issue I'm having is that the #submissions instance variable will always be the first day. So I'm trying to figure out how to get this to be responsive to the #num_days_ago which is being updated += 1 after leach loop. Any suggestions on how to make this happen?
Right now, it's displaying all of the days that have had posts since the first day a post was created, but the posts displayed for each day are all the 12 posts that were created on the first day.
#submissions always displays the submission of the first day because you've never changed it after you initialized it in the controller. Incrementing #num_days_ago in the view does nothing because the view does not use it.
If you want to display submissions since the first day, you need to set an array of submission from the first day to #submissions.
#submissions = num_days_since_first_day.times.map do |num_days_ago|
Submission.daily(num_days_ago).paginate(page: params[:page], per_page: 10).order('rank DESC')
end
And render each of them as you iterate in the view.
<%= render #submissions[num] %>
I think you can remove some redundant code and further refactor the code above, but that's the basic idea.
I have created a simple appointment system, and I now need to display something inside a loop if there's two or more appointments with the same date and time. The appointments are displayed in order of time, so they're just appearing one after the other.
Controller
def index
#todays_apps = current_user.appointments.order(time ASC)
end
View
<% #todays_apps.each do |app| %>
<%= app.business_name %>
<%= app.business_address %>
<%= app.time %>
<% end %>
I'm looking to display a message or icon the appointment shares a date and time with another appointment. Tried a collection of things with no luck.
You can group your collection by time and modify your iteration accordingly. You can group it like
#todays_apps.group_by(&:time)
The outcome will be something like
=> { timestamp1 => [app1,app2], timestamp2 => [app3], timestamp3 => [app4]}
Or you can try a quick hacky way like:
<% previous_time = nil %>
<% #todays_apps.each do |app| %>
<%= app.business_name %>
<%= app.business_address %>
<%= 'Your message or class or anything' if previous_time == app.time %>
<%= previous_time = app.time %>
<% end %>
Try Like this:
controller:
def index
#appointments = current_user.appointments.order("time ASC")
#todays_apps = #appointments.group_by(&:time)
end
View:
<% #todays_apps.each do |time, appointments| %>
<%= time %>
<% appointments.each do |appointment| %>
<%= appointment.business_name %>
<%= appointment.business_address %>
<% end %>
<% end %>
It will list all the appointments for particular time.
Thanks
I'm trying to loop through an array of the next 7 days, and for each, perform a query to find all the 'Time slots' that match, and add these to an object which I can loop through in my view. This is fairly simple in PHP, but I'm not sure of the syntax in rails. I have a situation where each day can have multiple 'delivery slots' available, and I need to display all these slots for the next week, by day.
So far in my controller I have
d = Date.today
d2 = d + 1.week
#days = (d..d2).to_a
#deliveries = []
#days.each do |d|
#deliveries[][dayname] = d.strftime("%a")
#deliveries[][slots] = Model.where("day = ?", d.strftime("%w"))
end
Then in my view, I want to do this
<% #deliveries.each do |d| %>
<%= d.dayname %>
<% d.slots.each do |s| %>
<%= slot data here %>
<% end %>
<% end %>
Where am I going wrong? Not quite sure of the syntax in rails where you'd use "as key => value" in php. Is this the most efficient way to go about it? It will result in 7 queries which isn't ideal
Thanks for any help
If your Model only has a day number, the slots will be the same for every week and you could do something like:
slots_by_day = Model.all.group_by(&:day)
#deliveries = (Date.today..Date.today + 6.days).each_with_object({}) do |day, dayname_groups|
dayname_groups.merge!(day.strftime('%a') => slots_by_day[day.strftime('%w').to_i])
end
It will fetch all models, group them by day number of the week and then build a hash mapping each day number with the day name ending up in a hash like:
=> {"Wed"=>[#<Model...>, #<Model...>, #<Model...>, #<Model...>],
"Thu"=>[#<Model...>, #<Model...>, #<Model...>, #<Model...>], "Fri"=>...}
The hash would be used like this:
<% #deliveries.each do |dayname, slots| %>
<%= dayname %>
<% slots.each do |s| %>
<%= slot data here %>
<% end %>
<% end %>
I have the following view code which displays events, along with headers informing the user if the following events occured today, yesterday, or in the past week.
It all works fine, but I would prefer to refactor it out of the view, I can't put it in a helper because it needs to maintain the variables state between loop iterations. Any idea how to tidy this up? thanks
<% displayed_week_already = false %>
<% displayed_yesterday_already = false %>
<% displayed_today_already = false %>
<% #events.each do |event| %>
<%= event.title &>
<% if (Time.now - 1.week) > event.created_at && !displayed_week_already %>
<% displayed_week_already = true %>
Events in past week
<% elsif (Time.now - 1.day) > event.created_at && (Time.now - 2.day) < event.created_at && !displayed_yesterday_already %>
<% displayed_yesterday_already = true %>
Events yesterday
<% elsif (Time.now - 1.day) < event.created_at && !displayed_today_already %>
<% displayed_today_already = true %>
Events in past day
<% end %>
<% end %>
Expected output would be:
Events in past day
John created a new artice
Dan commented on article 1
Sue deleted article 2
Events yesterday
Sue created a new article
Events in past week
Carol was promoted
Dan cerated a new article
I might do something like the following. I am leaving out the implemented methods defined on the model itself.
existing view
<%= render "events", :title => "Events in past day", :events => from_today(#events) %>
<%= render "events", :title => "Events yesterday", :events => from_yesterday(#events) %>
<%= render "events", :title => "Events in past week", :events => from_this_week(#events) %>
_events.html.erb
<% if events.present? %>
<%= title %>
<% events.each do |event| %>
<%= event.title %>
<% end %>
<% end %>
app/helpers/event_display_helper.rb
module EventDisplayHelper
def from_today(events)
events.select{|x| x.happened_today?}
end
def from_yesterday(events)
events.select{|x| x.happened_yesterday?}
end
def from_this_week(events)
events.select{|x| x.happened_this_week_before_yesterday?}
end
end
You could easily do this in the model, with named scopes (I'm assuming Rails 3 because that's what I know best). You'll need to define them yourself but they're pretty simple.
#last_week = #event.last_week
#yesterday = #event.yesterday
#today = #event.today
Then just iterate over each of the groups in your view. Should make it a lot cleaner and you won't need so much logic, as it's where it actually belongs.