I'm building a small app that takes things entered into an input field and displays them directly below that input field when entered.
My goal with this code is to separate those entries by date so that all things posted on June 1 are posted with one line break between them and the first entry of June 2 has 2 spaces between it and the entries from June 1.
This is my code and it's not acting as planned but I can't figure out why, I think it stems from line 3 and something I'm doing incorrectly. (Note: I'm aware this doesn't account for changes in month or year yet. I'll get to that once I figure out proper date spacing)
<% for i in (0..(#allLessons.count-1)) %>
<b><%= #date[i].created_at.strftime('%b %d')%></b><br/>
<% if #date[i].created_at.strftime('%d') == #date[i-1].created_at.strftime('%d') %>
<%= #date[i].created_at.strftime('%d') %> <br />
<% else %>
<%= #date[i].created_at.strftime('%d') %><br /><br />
<% end %>
<% end %>
From the controller:
#allLessons = Lesson.all
#date = Lesson.find(:all, :order => 'created_at ASC')
Any help you could lend on this would be hugely appreciated!
Blocks and iterators are where it's at.
#allLessons = Lesson.order('created_at ASC')
#dates = #allLessons.group_by { |lesson| lesson.created_at.beginning_of_day }.sort
<% #dates.each do |date, lessons| %>
<% lessons.each do |lesson| %>
<b><%= lesson.created_at.strftime("%d") %></b><br />
<% end %>
<br />
<% end %>
Annotated
First we get all of the lessons together. This is equivilant to find(:all, :order => 'created_at ASC'), but I like this newer, compact syntax
#allLessons = Lesson.order('created_at ASC')
Then we group them all together into a hash where the key is the date and the value is an array of records that were created on that day. beginning_of_day converts a DateTime into a Date where the time is set to 00:00:00. So, 2012-05-25 18:00 becomes 2012-05-25 00:00:00. This is so we can group the dates themselves without the time getting in the way
#dates = #allLessons.group_by { |lesson| lesson.created_at.beginning_of_day }.sort
#dates is now a hash where the keys are dates and the values are arrays of lessons from that date. for example, { '2012-05-24 00:00:00' => [ lesson_1 ], 2012-05-25 00:00:00' => [ lesson_2, lesson_3 ]
We then pass the hash into a block, where the key is the date, and the value is the array of lessons. This is saying, for each date...
<% #dates.each do |date, lessons| %>
Give me the lessons that belong to that date. And for each of those...
<% lessons.each do |lesson| %>
print out the date of the lesson
<b><%= lesson.created_at.strftime("%d") %></b><br />
<% end %>
before moving on to the next date, print a <br />
<br />
<% end %>
Related
pages_controller.rb
#past_challenges_by_years = #past_challenges.group_by { |t| [t.deadline.year, t.deadline.month] }
How can I break it down in the view with year and then subdivide it with month like this:
2014 # Years
01 # Months
Challenge
Challenge
02
Challenge
08
Challenge
2016
03
Challenge
08
Challenge
view.html.erb
<% #past_challenges_by_years.sort.each do |year, challenges| %>
<%= year %>
<%= month %> # I don't know how to define this.
<% for challenge in challenges %>
etc...
<% end %>
<% end %>
I would start by sorting the keys and then look up the challenges while iterating through those keys.
<% #past_challenges_by_years.keys.sort.each do |(year, month)| %>
<%= year %>
<br />
<%= month %>
<br />
<% #past_challenges_by_years[[year, month]].each do |challenge| %>
<%= challenge %>
<br />
Edit: Here is a new solution that only displays years and months once.
#past_challenges_by_years.keys.map { |a| a[0] }.uniq.sort.each do |year|
puts year
#past_challenges_by_years.keys.select { |a| a[0] == year }.map { |a| a[1] }.uniq.sort.each do |month|
puts month
#past_challenges_by_years[[year, month]].each do |challenge|
puts challenge
end
end
end
I think it should be simple enough to convert to ERB.
<% current_user.events.find(:all, conditions: ("start" > DateTime.now )).limit(5).each do |e| %>
<%= e.start %>
<% end %>
I get this error msg:
invalid date
this does not work because the format is not correct.
I can use e.start.to_date then I can compare the e.event with TimeDate.now but I don't know how to map the value to a DateTime.
If I do it like this:
<% current_user.events.map! { |e| e.start.to_date }.limit(5).each do |e| %>
<%= e.start %>
<% end %>
It's an array and therefore the good limit, where, select Active Record methods won't work anymore.
Basically I want to map all the start values to date then I want to compare them and show only today's events or future events but not from the past.
How would you solve this?
Can you try:
current_user.events.where("start > ?", Time.now.to_date)
I would like to make something like show posts from a particular date.
I have
<% date =Date.parse('2014-06-18') %>
<% if feed_item_users.created_at < (date+1).strftime('%Y-%m-%d') && feed_item_users.created_at > date %>
<li id="<%= feed_item_users.id %>">
<span class="content"><%= wrap(feed_item_users.content) %></span>
<span class="timestamp">
Published: <%= I18n.l feed_item_users.created_at, :format => :h %>
</span>
</li>
<% end %>
in my view I'm checking date.
Now I would like to make a date_time select to get date from my web in format like '2014-06-18' and make default today date.
I know that it should look like that:
<%= form_for(??????) do |f| %>
<div class="field">
<%= f.label :published_at %><br>
<%= f.datetime_select :published_at %>
</div>
<% end %>
but I don't know how to make it to variable because I need it only one time.
You're comparing dates against strings here which isn't reliable. In your ruby code you should always compare dates against dates (or times).
Your logic seems to be "if created at is greater than the start of today and less than the start of tomorrow", which can be massively simplified to "if it's today".
ie you can replace this
<% date =Date.parse('2014-06-18') %>
<% if feed_item_users.created_at < (date+1).strftime('%Y-%m-%d') && feed_item_users.created_at > date %>
with this
<% if feed_item_users.created_at.to_date == Date.today %>
The datetime_select is documented here
http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html
strftime returns string so when you apply less then operator it doesn't work.
Better way is to do it like this:
time = Time.new(2014, 06, 18)
if feed_item_users.created_at > time.at_beginning_of_day && feed_item_users.created_at < (time+1.day).at_beginning_of_day
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 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 %>