Formating variable within a string interpolation - ruby-on-rails

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.

Related

Rails 5.1, group_by, parse date, i18n

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 !

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

Rails with AJAX trimming contents of field

I have a model called Content with two fields 'before' and 'after'.
Before creating the record, I do some preprocessing on field 'before' and store it in 'after'. No problem here.
Problem is when I load the show page the contents in 'before' display incomplete. I'm trimming white spaces after a period if there are 2 or more...
e.g.
"this is. some text. with many spaces. after the periods."
The view shows me that 'before' looks like this:
"this is. some text. with many spaces. after the periods."
If I look at the .json version the 'before' field contains the original format - why then does the rails view (non-json) present the 'before' as being "trimmed"?
This is my _content.html.erb
<li><%= content.before %></li>
<li><%= content.after %></li>
This is my show.js.erb
$("#main").html("<%= escape_javascript(render #content) %>");
This is the show definition in contents_controller.rb
respond_to :html, :json
def show
#content = Content.find(params[:id])
respond_with(#content)
end
This is the pre-processing in my model content.rb
class Content < ActiveRecord::Base
before_validation :format_params
def format_params
rm_spaces = /\.\s{2,}/ # regex to rm extra spaces
new_format = '. ' # only one space after period
self.after = before.gsub(rm_spaces, new_format)
end
end
And here are some screenshots of what I mean.
Edit
I believe this is the code that is getting executed since I tried Swards recommendation and it did not work.
This is the code for my highlighting function in my contents_helper.rb
def highlight_changes(text)
highlighter = '<span style= "background: yellow">\1</span>'
matcher = /(\.\s{2,})/
text.gsub(matcher, highlighter).html_safe
end
This is the code in show.html.rb
<p>
<strong>Before:</strong>
<!-- call the helper method to highlight changes made -->
<%= highlight_changes #content.before %>
</p>
You can put a .before class on the before li and add this to css to see it as it was entered.
<li class="before"><%= content.before %></li>
<li><%= content.after %></li>
in the css
.before {
white-space: pre;
}
I think it is the browser that omits extra spaces. You can use to make a whitespace instead.
To transform your string you could try
content.before.gsub(' ', ' ').html_safe
This replaces each space with and then tells rails not to escape the html characters ( ).
Warning:If the before field is input by users then using html_safe is dangerous as it could allow users to inject malicious code.

reverse order of publications grouped by year

For archiving the publications in my Rails app, I group the publications by year:
app/controllers/publications_controller.rb
...
def series
#publications = Publication.all
#publications_year = #publications.group_by { |p| p.year}
end
then in the view, I want to have a link for each publication year:
<% #publications_year.sort.each do |year, pubs| %>
<li><i class="fa fa-folder left"></i><%= link_to year, archive_path(year) %></a>
</li>
<% end %>
this works fine, the result is:
2012
2013
2014
However, I need to reverse the order, so the links should be ordered like this:
2014
2013
2012
...
But I can't figure out how to this
Does anyone know how I can reverse the order of the year links?
thanks for your help,
Anthony
You can also let the db do the ordering.
#publications_year = #publications.order('year DESC').group_by { |p| p.year }
If you do it this way, you don't need to call sort anymore.
did you try using the reverse method?
#publications_year.sort.reverse.each
source: http://apidock.com/ruby/Array/reverse

Argument out of range Rails 4 and bootstrap3-datetimepicker-rails

I'm using the bootstrap3-datetimepicker-rails gem to let users store the scheduled_date of a WorkOrder in my application (a 'DateTime' property), but I'm getting an argument out of range error when the user submits the form to create the WorkOrder, and the date is very different than what was selected whenever the user pops open the edit screen. The funny thing is that it used to work, but I don't know what code could have changed to break it.
I added the required dependencies & included the proper directives in my CSS/JS files:
gem 'momentjs-rails', '~> 2.5.0'
gem 'bootstrap3-datetimepicker-rails', '~> 3.0.0'
As far as I can tell, my code looks identical to the example on the documentation. Here's the snippet of my form:
<div class="row">
<div class="col-md-4">
<div class="form-group">
<%= f.label :scheduled_date %>
<div class='input-group date'>
<span class="input-group-addon"><span class="fa fa-calendar"></span></span>
<%= f.text_field :scheduled_date, class: 'form-control input-lg', id: "service_date_picker" %>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(function () {
$('#service_date_picker').datetimepicker({
icons: {
time: "fa fa-clock-o",
date: "fa fa-calendar",
up: "fa fa-arrow-up",
down: "fa fa-arrow-down"
}
});
});
</script>
EDIT (forgot to add controller code - super simple):
work_orders_controller.rb
def create
#work_order = WorkOrder.new(work_order_params)
... [it errors on the line above]
end
And my parameter whitelist:
def work_order_params
params.require(:work_order).permit(:caller_name, :brief_job_details, :contract_price, :quoted_by, :job_description, :scheduled_date, :time_materials_details, :sheduled_time, :contact_name, :payment_method, :notes, :customer_id, :job_site_id)
end
And an example of the parameters that give the argument out of range error when I save the form:
work_orders_attributes"=>{"0"=>{"caller_name"=>"Justin", "time_materials_details"=>"", "contract_price"=>"", "quoted_by"=>"", "payment_method"=>"", "job_description"=>"", "scheduled_date"=>"05/23/2014 1:28 PM", "notes"=>""}}
Same as my customers_controller.rb where I have a nested form for a WorkOrder inside of the new customer form (everything else on that form works perfectly):
def create
#customer = Customer.new(customer_params)
... [errors above]
end
The date and time saves correctly if it is within 24 hours of now, but even when it saves correctly, the date displays completely weird and unformatted in the text field when I go to edit that WorkOrder. For instance:
When I select the date from the date picker: 05/06/2014 10:28 AM
When I edit the WorkOrder: 2014-06-05 10:28:00.000000
Any ideas? Any preference for whether I should make that field a Date, Time, or DateTime (currently)? Right now, we're working in Central time zone, but that won't always be the case.
Thanks in advance for pointing me in the right direction!
#Uri Agassi is right: it's the values that you're passing to create the WorkOrder that are the most relevant here.
Try putzing around with the custom date formatting options provided to you by bootstrap-datepicker. If you can get a format that looks good and is easy to parse on the backend, then you'll want to intercept that parameter before it goes to the model for validation.
Regardless of what you'll go with for date formatting on the client-side, you'll still want to parse it into a useable Date or DateTime object server-side in your controller. Check out DateTime#strptime. You can also call #strptime on Date.
Untested, but the idea is there:
def create
order_params = work_order_params
order_params[:scheduled_date] = Date.strptime(order_params[:scheduled_date],
'%m/%d/%Y %I:%M %p')
#work_order = WorkOrder.new(order_params)
end
You can remove the modifications from the Controller all together by updating the values in the model. I feel this is a much cleaner (and reusable) approach.
class Work < ActiveRecord::Base
def scheduled_date=(date)
begin
parsed = Date.strptime(date,'%m/%d/%Y %I:%M %p')
super parsed
rescue
date
end
end
end
It's me helped:
To file application.js writing to end file:
$(function() {
$('.datepicker').datepicker({format: 'dd-mm-yyyy'});
});
This plugin uses moment.js. Basically you need to choose the time format you would like.
example
$(function () {
$('#datetimepicker').datetimepicker({format: 'MMMM Do YYYY, h:mm'});
});

Resources