Rails 5.1, group_by, parse date, i18n - ruby-on-rails

I have a very specific problem to get the month name in I18n. I'm grouping some infos per month and year, and it looks like that when I want to translate it, all the month with a specific caracter like é or û aren't working, where the rest is. Let me show you how it looks like :
Helper :
def user_spendings_paginate
user.spendings.all.order('date DESC').paginate(:page => params[:page], :per_page => 15)
end
def grouped_spendings
user_spendings_paginate.group_by{ |t| t.date.to_date == DateTime.now.to_date }
end
def month_wise_sorted_spendings
if user_spendings_paginate.present?
user_spendings_paginate.group_by{ |t| t("date.month_names")[t.date.month] + " " + t.date.year.to_s }
end
end
So as you can see, I call all the user.spendings. I group them twice, the first to get the date of the day and the other to get the rest per month and year. As you can see I i18n the month name. In my yml file I have that :
month_names:
-
- Janvier
- Février
- Mars
- Avril
- Mai
- Juin
- Juillet
- Aout
- Septembre
- Octobre
- Novembre
- Decembre
I tried to remove the é from Décembre and the û from Août to try, but the problem remains the same.
My controller :
if params[:month]
#date = Date.parse("#{params[:month]}")
else
flash[:error] = t(".something_wrong")
redirect_to myspendings_path(locale: I18n.locale)
end
And my view :
<% date_in_link = " #{month}" %>
<p><%= link_to myspendingsdetail_path(:month => month, locale: I18n.locale), class: "btn btn-secondary" do %>
<i class="fa fa-link"></i>
<%= date_in_link %>
<% end %>
So basically what I'm doing is that I group the spendings per month and year. Then I loop trough all the user.spendings and I add this part of code above in the mix so you have a link according the date that you can click and sends you to a new page whith more infos just about this month of the year.
It works, but just for the month with no specific caracters. If I try with Février I got this as a message : invalid date for #date in the controller.
I assume it is coming from the special caracter as the rest is working.
I hope the explanation are clear, I tried my best. If you need more stuff let me know.
I think that the #date variable is missing something, but I'm not sure. Anybody to help ?
EDIT :
My url looks like this when it works :
http://localhost:3000/fr/myspendingsdetail?month=Janvier+2018
When it doesnt work :
http://localhost:3000/fr/myspendingsdetail?month=Decembre+2018
Interesting but when I put the month like this :
http://localhost:3000/fr/myspendingsdetail?month=12+2018
It works, so it's really a caracter problem
EDIT 2 :
Well it works... if I put 12 he bring me on february, same for 2, but if I put 1 for january same error as before, invalid date.

YES ! I got it !
I share my answer in case anybody needs it once.
I changed my helper :
user_spendings_paginate.group_by{ |t| (Date::MONTHNAMES[t.date.month] + " " + t.date.year.to_s) }
I keep the names of the month in english in the background, if I can say...
Then the view :
<% date_in_link = " #{month}" %>
<p><%= link_to myspendingsdetail_path(:month => month, locale: I18n.locale), class: "btn btn-secondary" do %>
<i class="fa fa-link"></i>
<%= l date_in_link.to_date, format: :pdf %>
<% end %>
As I get a String out of my helper, and I pass that trough params with my links I thought that it was there that I should change the language. So I wrote this :
l date_in_link.to_date, format: :pdf and in my yml file I went for a custom format like so : pdf: "%B %Y" for month and year.
Result :
(link)Février 2018
- spending
- spending
(link)Janvier 2018
- spending
- spending
And when I click on the link it passes the params in english but who cares. On the next page I got the date back in the language I want anyway. Mission complete !

Related

Formating variable within a string interpolation

I have a string interpolation that looks like this:
<ul class="list-group">
<% #top_ten_cashflows.each do |transaction|%>
<li class="list-group-item"> <%=" #{ transaction.date.format('%b') } - #{transaction.category.name} - #{transaction.amount}"%></li>
<%end%>
</ul>
Rails brings up the following error when i try to format the date:
NoMethodError at /Dashboard
private method `format' called for Wed, 20 Jul 2016:Date
The controller looks as follows:
def dashboard
##cashflows = current_user.cashflows
# cashflows_sums =#cashflows.inject do |sum,element|
#cashflows = Cashflow.where(user_id: current_user.id).joins(:category)
#top_ten_cashflows = #cashflows.order(:date).limit(10)
end
How do i get the date to be formatted within the string interpolation with the day and short month.
transaction.date.strftime('%b')
https://apidock.com/ruby/Date/strftime
Even better, use I18n localization Date/Time formats, it is easy, flexible and adds an extra level of customization per locale.
# app/views/home/index.html.erb
<p><%= l Time.now, format: :short %></p>
You can use the default Rails Date/Tme formats or add your custom formats.

Splitting up an each block, into blocks depending on content

This is a tricky one to express, I'll give it a shot though:
I have defined #model = Model.all which includes both depart_at and arrive_at. I now need to run through these, in groups of date. (Each is a datetime in the database).
I've tried a few things, but I can't seem to get anything to work here.
<% #departure_times.each do |departure_time| %>
<% end %>
is the current code. I can't seem to find anything in the Rails API about, what I can do to chunk up by the date of depart_at.
Edit:
The expected outcome is something alike:
**date** - 10:15, 11:15, 20:30
**date** - 11:15, 12:30, 14:15
etc - The meaning for this, is to group the output by the date of the timestamp.
One might prepare the chunked array in the controller:
#dt_grouped = #departure_times.group_by do |departure_time|
Date.parse(departure_time.depart_at.to_s).to_s
end
This will produce a Hash instance like:
{ '2016-03-08' => [dt1, dt2, dt3,...], ...}
and then in view:
<% #dt_grouped.each do |date, times| %>
<%= date %> — <%= times.join ', ' %>
<% end %>

Adding dates to the database that can be used to specify an active week

I am in the process of creating an competition app that needs to be pretty much autonomous. The app has a resource called 'Weeks' and each week has many 'Entries'. Users can add an entry to the week, and then they can be voted on.
The week has a database column called 'start_date' and if I populate this with a string, eg "16-03-2015" then on the Show view I can pull in the weeks params and compare the string to todays date and set whether the vote buttons are active or not.
In my weeks controller I use a before action called set_dates and I set a couple of variables
def set_dates
#today = Date.today
#weekstart = Date.parse(#week.active_date)
#weekend = Date.parse(#week.active_date)+7
end
I can then set if and else statements on the view to show the vote buttons if the week is 'active', ie. todays date is within the active_date + 7 days
<% #entries.each do |entry| %>
<div class="entry">
<%= image_tag(entry.photo(:thumb)) %>
<%= entry.cached_votes_up %>
<% if (#weekstart..#weekend).include? #today %>
<%= link_to "Upvote", upvote_week_entry_path(entry.week_id, entry) %>
<%= link_to "Downvote", downvote_week_entry_path(entry.week_id, entry) %>
<% end %>
</div>
<% end %>
This was fine until I realised I needed to have an 'active week' outside of the show view. I want to put a link into the Navigation Bar in the application_layout to 'This Weeks Comp', and I need this week to point to whichever week voting is active on. But without finding the week by its ID, then cross referencing it's active_date, I am unsure how to do this. Any help would be greatly appreciated.
Thanks!
If anyone else is find this looking to solve a similar problem, I solved the issue by adding an end_date column to the weeks resource, and then assigned a variable to an arel query in the application controller
App-Controller
before_action :active_week
protected
def active_week
#aweek = Week.where("? BETWEEN start_date AND end_date", Date.today)
#active = #aweek.first
end
Application Layout
<%= link_to "This Week", #active %>

Rails - How to pass data from view or url to helper

In Rails I'm using code from Railscasts #213 revised to build a calendar. I'm using it to display Event hours for each day.
The helper code sets the background-color for today, so you can easily see which day is today.
I have it working so that you can click on a day and a table will show detail records of Events for that day.
This is the code that is executed when the user clicks on a day in the calendar:
<div><%= link_to 'View' , events_index7_path(:date_selected => date), :class => 'btn btn-mini'%></div>
That puts the selected day into the url, like this:
.../events/index7?date_selected=2013-11-22
And the view tests for the day_selected like this:
<% current_user.events.where(:event_date => #date_selected).each do |event| %>
I would like to set the css background-color for the date_selected
I'm trying to add the dayselect class to the helper:
def day_classes(day)
classes = []
classes << "today" if day == Date.today
classes << "dayselect" if day == #date_selected
classes << "notmonth" if day.month != date.month
classes.empty? ? nil : classes.join(" ")
end
But, it doesn't recognize #date_selected
I also tried this:
classes << "dayselect" if day == params[:date_selected]
UPDATE1:
This is a pic of the calendar so you better understand what I'm doing:
UPDATE2
View code for the calendar:
<%= calendar #date do |date| %>
<%= date.day %>
<% hours = current_user.events.where(:event_date => date).sum(:hours) %>
<% if hours != 0 %>
<div class="sumhours"><%= hours %></div>
<% else %>
<div> - </div>
<% end %>
<div><%= link_to 'View' , events_index7_path(:date_selected => date), :class => 'btn btn-mini'%></div>
UPDATE3
If I stop execution at the helper code to set the class, I find this:
Request parameters
{"date_selected"=>"2013-11-21", "controller"=>"events", "action"=>"index7"}
How do I access the date_selected parameter?
UPDATE4
This will highlight a specific date converted from a string:
classes << "dayselect" if day == DateTime.strptime("2013-11-18", "%Y-%m-%d")
But, if I used this:
classes << "dayselect" if day == DateTime.strptime(params[:date_selected], "%Y-%m-%d")
I get:
undefined local variable or method `params' for #<CalendarHelper
I couldn't figure out how to do it with Rails, so I used jQuery.
Used pure.js to get the url.
Here's the jQuery (Coffeescript):
url = $.url().param("date_selected")
$("#monthcalendar td").each ->
$(this).addClass "dayselect" if $(this).attr('class') == url

How do I do a grouping by year?

I have a books model with a date type column named publish_date. On my views I'm iterating through the books and I want to group the books by year such that I have a heading for every year and books that were published on that year to be listed below the year heading.
So by starting with "2010" all books published on 2010 would be listed, then another heading "2009" with all books published in 2009 listed below it and so forth.
<% #all_books.each do |book| %>
<%=link_to book.title + ", (PDF, " + get_file_size(book.size) + ")" %>
<% end %>
By doing a book.publish_date.strftime("%Y") I am able to get the year but I do not know how to group the entries by year. Any help on this would be appreciated.
You can use group_by (see API) like (of the top of my head
<% #all_books.group_by(&:year).each do |year, book| %>
...
<% end %>
def year
self.created_at.strftime('%Y')
end
< % #all_books.group_by(&:year).each do |year, book| %>
Year < %= year %>
# render books here
< % end %>
What say?
You can use group_by for convenience, but your need can be better served by relying on DB for sorting and a each loop. This avoids the cost of client side sorting and hash manipulations for grouping.
Somewhere in your controller
#all_books = Book.all(:order => "publish_date DESC")
In your view
<%year = nil
#all_books.each do |book|
if year.nil? or year > book.publish_date.year
year = book.publish_date.year
%>
<h1> <%=year%><h1>
<%end % >
<%=link_to book.title + ", (PDF, " + get_file_size(book.size) + ")" %>
<%end %>
The quick and dirty approach is to simply group_by the year and iterate over those:
#all_books.group_by { |b| b.created_at.year }.each do |year, books|
# All books for one year, so put heading here
books.each do |book|
# ...
end
end
This requires sorting within the Rails application, so you will need to retrieve all relevant records in order to have the data properly organized. To do the sort on the server you will probably need to introduce a year column and keep it in sync with the created_at time.

Resources