map timestamp to DateTime - ruby-on-rails

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

Related

Rails 5: loop through an array of records and indicate the new records

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.

Rails iteration over arrays and hashes

I am trying to iterate over what I think is a hash in rails. I used deep_pluck gem to get the values of a Model including some values from the associations. Like this:
Continent.deep_pluck(:link_name, :name, 'countries' => [:link_name, :name])
this returns:
[{"link_name"=>"europe", "name"=>"europe", "countries"=>[{"link_name"=>"countryname", "name"=>"countryname"}]}]
I am trying to iterate this like this:
<% results.each do |continent| %>
<% continent.each do |link_name, name, countries| %>
<%= link_name %>
<% end %>
<% end %>
which in return this:
link_name
name
countries
I tried a lot of different ways and methods and I still can't get the desired output which is to print out the values of :link_name and :name and also another object of countries to iterate them over again for their name etc.
I'm trying to build a navigation menu which has a list of each continent with a submenu of the countries of the continent. I use pluck because I just want the names and link_names of the database.
Thank you very much!
When you iterate over a hash, you get access to the keys and values.
If you look at what's printing out, you're getting the keys of each hash. Your output might make more sense if you set the parameters to what they actually are.
<% results.each do |continent| %>
<% continent.each do |key, value| %>
<%= key %>
<% end %>
<% end %>
This should be enough to get you further along. To achieve what you want, you'll need to check each key and do something with the value based on what the key is.
Perhaps try something like:
[{"link_name"=>"europe", "name"=>"europe", "countries"=>[{"link_name"=>"countryname", "name"=>"countryname"}]}].each do |continent|
continent.each do |k,v|
case k
when 'countries'
v.each do |country|
country.each do |k,v|
puts " - #{v}"
end
end
else
puts v
end
end
end
(Naturally, you'll need to add the erb markup. And the "puts" are just for example to run this in console.)
Which will give you:
europe
europe
- countryname
- countryname
Thank you very much for your suggestions, i finally managed to make it work like this:
<% results.each do |continent| %>
<li class="has_children"><%= continent["name"] %>
<ul class="sub_menu">
<% continent["countries"].each do |country| %>
<li><%= country["name"] %>
<% end %>
</ul>
</li>
<% end %>

Looping through unique (excluding a single column) values in view

I am keeping track of which users edit text files stored as database entries.
I have a credit model that keeps track of the user, file edited, and a timestamp of when the edit occurred.
In my controller, I have a query that selects the editors of an entry, and joins a time stamp from the credit model.
#editors = User.select("name, users.id, credit.created_at").joins("INNER JOIN credits ON credits.user_id = users.id WHERE credit.file_id = " + x)
In my view, I do not want to display duplicate editors, but the unique timestamp that is joined to the user is causing duplicate editors to print
<% #editors.uniq.reverse_each do |e| %>
<%= link_to e.name, user_path(e.id) %>
<%= e.created_at %>
<% end %>
Is there a way that I can exclude a certain column from the uniq comparison in my view?
This is not the cleanest solution. but this is what I would do if I was a time crunch
<% editor_id = 0 %>
<% #editors.uniq.reverse_each do |e| %>
<% unless editor_id == e.id %>
<%= link_to e.name, user_path(e.id) %>
<%= e.created_at %>
<% editor_id = e.id %>
<% end %>
<% end %>
What I am doing here is initializing a variable called editor_id and then check if its the same a the editor id. if its false then it displays the editor
I hope that this helps and puts you in the right track

Rails creating multidimensional array within loop

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

Having trouble parsing and spacing date/fixnum objects

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

Resources