comparison of ActiveSupport::TimeWithZone with 12 failed - ruby-on-rails

I have restaurants where user can make reservations. For reservations, I set my time attribute as integer. I then used a helper to display time selection(radio button) such as 14 to 2:00pm.
def new_time(h)
if h > 12
(h-12).to_s + ":00 PM"
elsif h == 12
h.to_s + ":00 PM"
else
h.to_s + ":00 AM"
end
end
Reservation time options are displayed on Restaurant page:
<%= form_for([#restaurant, #reservation], :html => {:class => 'reserve-form'}) do |f| %>
<div class="times">
<% #restaurant.hours_open.each do |h| %>
<%= f.radio_button :time, h %>
<%= f.label "time_#{h}", new_time(h), class: "reserve" %>
<% end %>
</div>
<div class="align">
<%= f.label :party_size,'Please enter party size' %>
<%= f.text_field :party_size %>
</div>
<div class="align">
<%= f.submit %>
</div>
Now when reservation is done, I redirect to User Profile to display that reservation. Everything works fine on development side but after deploying to heroku, I get error "We're sorry, but something went wrong." when making a reservation and I think it has something to do with reservation time displayed on user page shown below.
When I check heroku logs this is the error:
ActionView::Template::Error (comparison of ActiveSupport::TimeWithZone with 12 failed):
<% #user.reservations.each do |reservation| %>
<div class="user-reservation align">
<p>Restaurant: <%= reservation.restaurant.name %></p>
<p>Reserved Time: <%= new_time(reservation.time) %></p>
<p>Party Size: <%= reservation.party_size %></p>
<p>Added on: <%= reservation.created_at.strftime("%B %d, %Y") %></p>
app/helpers/application_helper.rb:3:in `>'
app/helpers/application_helper.rb:3:in `new_time'
app/views/users/show.html.erb:19:in `block in _app_views_users_show_html_erb__1649677434053595894_70057403913200'
app/views/users/show.html.erb:16:in `_app_views_users_show_html_erb__1649677434053595894_70057403913200'

You are comparing the attribute reservation.time which is a ActiveSupport::TimeWithZone with an integer.
If your datatype is a time, why don't use just format it with strftime ?
<p>Reserved Time: <%= reservation.time.strftime("%I:%M%p") %></p>

Related

Rails 5 fields_for only sends last params

I have been hitting my head against a brick wall so it is time to seek smarter people.
I am trying to create multiple records of one model using form_tag and fields_for. I have been following all the help/issues/guides I can find but it doesn't seem to work for me. I am wondering if it something that changed going to Rails 5 but more likely it is me.
Basically I want a new/create version of the task system listed at the bottom of the api page, similar to this guys puppy creator.
The "new" page loads fine with as many records as I like, so that part is ok but it doesn't seem to be creating a collection to send through, it is just overriding and thus sending through the last set of params so only creating one record.
What I have.
# routes
resources :container_returns
controller
# container returns controller
def new
#containers = Container.where(id: params[:container_ids])
#container_returns = []
#containers.each do |container|
#container_returns << ContainerReturn.new(
{
container_id: container.id,
quantity: container.amount,
uom: container.uom,
material_restriction_id: container.material_restriction_id
}
)
end
end
view
# new.html.erb
<%= form_tag container_returns_path, method: :post do %>
<% #container_returns.each do |container_return| %>
<%= fields_for 'returns[]', container_return, hidden_field_id: true do |cr| %>
<div class="field">
<%= cr.label :container_id %>
<%= cr.number_field :container_id %>
</div>
<div class="field">
<%= cr.label :material_restriction_id %>
<%= cr.number_field :material_restriction_id %>
</div>
<div class="field">
<%= cr.label :quantity %>
<%= cr.text_field :quantity %>
</div>
<div class="field">
<%= cr.label :uom %>
<%= cr.text_field :uom %>
</div>
<% end %>
<% end %>
<%= submit_tag "lots of returns" %>
<% end %>
which submits
# params submitted
Started POST "/container_returns" for 127.0.0.1 at 2018-10-19 11:00:48 +0200
Processing by ContainerReturnsController#create as HTML
Parameters: {
"utf8"=>"✓", "authenticity_token"=>[removed],
"returns"=>{"container_id"=>"405", "material_restriction_id"=>"", "quantity"=>"100.0", "uom"=>"kg"}, "commit"=>"lots of returns"
}
hopefully it is just something stupid that I missed.
UPDATE:
if I add an index to the form it now believes me that my objects are different and sends through all the params I need.
<% #container_returns.each_with_index do |container_return, index| %>
<%= fields_for 'returns[]', container_return, index: index do |cr| %>
[...]
as mentioned in the update, if I add an ID to the initial create it builds the correct array that I was expecting. What I also found was if I send through an index position that also works.
<% #container_returns.each_with_index do |container_return, index| %>
<%= fields_for 'returns[]', container_return, index: index do |cr| %>
[...]
gives me what I was expecting
Parameters: {
"returns"=>{"0"=>{"container_id"=>"400",...},
"1"=>{"container_id"=>"401",...},
etc.
},
"commit"=>"lots of returns"
}

Two Similar Partials, One Giving Error, Other Is Fine

I have two partials, that are almost exactly the same, except one is a full view, and the other is a compact. They are both under 'projects' view, but one works correctly, and the other gives errors:
projects/_project.html.erb
<div class="pure-u-1-3">
<%= link_to project do %>
<div class="project">
<h4 class="red marginless"><%= truncate( project.title, length: 22, separator: ' ') %></h4>
<p class="left marginless"><strong>By:</strong> <%= project.user.username %><br>
<strong>Genres:</strong> <%= truncate( project.genre2, length: 25, separator: ' ') %><br><br>
<strong>Description:</strong><br>
<%= truncate( project.description, length: 60, separator: ' ') %><br>
<strong>Needs:</strong><br>
<%= truncate( project.looking_for, length: 60, separator: ' ') %></p>
</div>
<% end %>
<% if #projects.size == 0 %>
<em> no projects found with that criteria </em>
<% end %>
</div>
projects/_short.html.erb
<div class="pure-u-1-3">
<%= link_to project do %>
<div class="project">
<h4 class="red marginless"><%= truncate( project.title, length: 22, separator: ' ') %></h4>
<p class="left marginless"><strong>By:</strong> <%= project.user.username %></p>
</div>
<% end %>
</div>
Now, this is the part of the view using these partials:
dashboards/index.html.erb
<% if #projects.length > 0 %>
<div class="pure-u-1" id="projects"><h3 class="red"><%= current_user.username %>'s Owned Projects</h3>
<%= render :partial => 'projects/short', :collection => #projects %>
</div>
<% end %>
When I have 'projects/project' it works perfectly, no issues.
When I put 'projects/short' it gives me this error:
undefined local variable or method `project'
This error is given everywhere the word project is used on _short, unless I use #project, but then it gives me this error:
undefined method `title' for nil:NilClass (same for user)
I do not understand how the partials can be in the exact same spot, and used the exact same way, in the exact same spot, but one works and the other does not. Is there code I may have done in the past, that I am missing that makes this work?
You need to supply the as: :project option to the render partial call as:
<% if #projects.length > 0 %>
<div class="pure-u-1" id="projects"><h3 class="red"><%= current_user.username %>'s Owned Projects</h3>
<%= render :partial => 'projects/short', :collection => #projects, as: :project %>
</div>
<% end %>
This will make project local variable available within the partial projects/short.
The reason you are getting the error is because (from the documentation on rendering collections within Using render):
When a partial is called with a pluralized collection, then the
individual instances of the partial have access to the member of the
collection being rendered via a variable named after the partial.
Okay, so before I actually saw the above answer, I was still sorting through documentation, and from my best understanding, I actually just changed everything that said project to compact now like:
<h4 class="red marginless"><%= truncate( compact.title, length: 22, separator: ' ') %></h4>
<p class="left marginless"><strong>By:</strong> <%= compact.user.username %></p>
Is this the 'wrong' way to do it? It seems to be working perfectly now...

Order by time_field

I have a database table called "bookings" which users can select the 'time_from' and 'time_to' in which they want the booking done.
When adding these fields to the database I added them as a time_field.
<%= f.label :time_from, "From (24hr Clock)" %>
<%= f.time_field :time_from %>
<%= f.label :time_to, "To (24hr Clock)" %>
<%= f.time_field :time_to %>
The form works and saves correctly but my problem is the order. Below is my controller code and subsequently my view to display the time and its output. Any idea on how to order these by time correctly?
Controller:
def show
#location = Location.find(params[:id])
#booking = Booking.order("time_to")
#company = Company.all
end
View:
<% 0.upto(11.to_i).each do |day_count| %>
<span class="col-md-3 booking-times">
<h4><%= time_tag(Date.today + day_count.days) %></h4>
<span class="label label-danger no-bookings">No Bookings</span>
<% #booking.each do |b| %>
<% if b.date == Date.today + day_count.days && b.type == "Meeting" %>
<% if b.location == params[:id] %>
<span class="label label-info booking-time">
<%= time_tag(b.time_from, :format=>"%H:%M") %> -
<%= time_tag(b.time_to, :format=>"%H:%M") %>
</span>
<% #company.each do |c| %>
<% if c.id == b.company %>
<%=link_to c.name, c %></br>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
</span>
<% end %>
Output: (For first day time)
09:30 - 10:30
22:00 - 23:00
07:30 - 08:30
I appreciate this is not the nicest looking code. I would like the above output to order by time. Any ideas? I have tried to order in the controller, this effects the layout but not in the correct order still. I think the dat attatched to the time_to input may be having ian affect? Thanks!
Have you tried this:
#booking = Booking.order(time_to: :desc)
Can you please try this:
#booking = Booking.order('time_to desc')

Ruby on rails forms, partial

I have index page:
<div>
<%= render :partial => "ev_calendar" %>
</div>
<% Project.events.each do |event| %>
<%= link_to l(event.published_at, :format => "%d.%m.%Y"), event %>
<div>
<%= event.description %>
</div>
<% end %>
ev_calendar:
...
<%= day %>
...
day - it's a day oncalendar, only a number. How can I make this da like link, after clicking on this link - my page reloaded and first example-code show events only for this day (by created_at attribute).? plz help me
You can do this:
<%= link_to day, your_path_to_action(:day => day) %>
then you can catch :day parameter in params[:day]. In action you can verify this parameter and do something like this:
Project.events.where(["DAY(created_at) = ?", params[:day]])

Why does Rails screw up timezones when I am editing a resource?

Steps to produce this:
prompt>rails test_app
prompt>cd test_app
prompt>script/generate scaffold date_test my_date:datetime
prompt>rake db:migrate
now edit your app/views/date_tests/edit.html.erb:
<h1>Editing date_test</h1>
<% form_for(#date_test) do |f| %>
<%= f.error_messages %>
<p>
RIGHT!<br/>
<%= text_field_tag #date_test, f.object.my_date %>
</p>
<p>
WRONG!<br />
<%= f.text_field :my_date %>
</p>
<p>
<%= f.submit 'Update' %>
</p>
<% end %>
<%= link_to 'Show', #date_test %> |
<%= link_to 'Back', date_tests_path %>
now edit your config/environment.rb:
#add this
config.time_zone = 'Central Time (US & Canada)'
This recreates the problem I am having in my actual app. The problem with my app is that I'm storing a date in a hidden field and rendering a "user friendly" version. Creating a resource works fine but as soon as I try to edit it the time changes (it adds the difference between my current time zone configuration and UTC). go to http://localhost:3000/date_tests/new and save the time then go to reedit it and you will have two different representations of the date/time one which will save incorrectly and the other that will.
EDIT: One might ask why not just use the one that works. The problem with this is that I am using a nested attribute so i can't exactly do this. I tried doing this:
# from my real app:
<% appt.fields_for :time_slot do |ts| %>
<%=h ts.object.start_at.strftime('%T') %>
<%= hidden_field ts.object.start_at, :start_at %>
<%= hidden_field ts.object.end_at, :end_at %>
<% end %>
but the html results as:
<div>
10:00:00
<input id="2010-05-30_10:00:00_-0500_start_at" name="2010-05-30 10:00:00 -0500[start_at]" type="hidden">
<input id="2010-05-30_10:10:00_-0500_end_at" name="2010-05-30 10:10:00 -0500[end_at]" type="hidden">
<input id="appointment_block_appointments_attributes_0_time_slot_attributes_id" name="appointment_block[appointments_attributes][0][time_slot_attributes][id]" type="hidden" value="95">
</div>
ok it turns out that i need to override the "convention" and have something like:
<%= ts.hidden_field :start_at, :value => ts.object.start_at %>
using :value will give me the timezone difference as well which fixed my problem!

Resources