8

I've only been working with Ruby for a short time and I've hit a wall today while working on a calendar to put requests on. I spent time searching through different undefinied method error documents on stackoverflow, the ruby guides, etc. as well as looking into strftime. I found a solution that partially solved my problem using try, but now it is not actually passing the strftime through to show on the request, even though the rails server is picking it up in the post. I can get to my calendar fine, and hit the new request button, fill out the form, but when I go to post that form the browsers gives me this:

undefined method `strftime' for nil:NilClass

Extracted source (around line #3):

1: <h1><%= @vacationrequest.request_name %></h1>
2: 
3: <p class="info">Requested For <%= @vacationrequest.request_date.strftime("%B %e, %Y") %></p>
4: 
5: <%= simple_format @vacationrequest.message %>
6: 

And I get this error on the Rails server:

Started GET "/vacationrequests/1" for 127.0.0.1 at 2012-10-17 15:18:14 -0400
Processing by VacationrequestsController#show as HTML
Parameters: {"id"=>"1"}
←[1m←[35mVacationrequest Load (0.0ms)←[0m SELECT "vacationrequests".* FROM "v
acationrequests" WHERE "vacationrequests"."id" = ? LIMIT 1 [["id", "1"]]
Rendered vacationrequests/show.html.erb within layouts/application (15.6ms)
Completed 500 Internal Server Error in 31ms

ActionView::Template::Error (undefined method strftime' for nil:NilClass):
1: <h1><%= @vacationrequest.request_date %></h1>
2:
3: <p class="info">Requested For <%= @vacationrequest.request_date.strftime(
"%B %e, %Y") %></p>
4:
5: <%= simple_format @vacationrequest.message %>
6:
app/views/vacationrequests/show.html.erb:3:inapp_views_vacationrequests_sho
w_html_erb_217743956_18446544'

This is my show view:

<h1><%= @vacationrequest.request_name %></h1>

<p class="info">Requested For <%= @vacationrequest.request_date.strftime("%B %e, %Y") %></p>

<%= simple_format @vacationrequest.message %>

<p>
  <%= link_to "Edit Request", edit_vacationrequest_path(@vacationrequest) %> |
  <%= link_to "Back to Requests", vacationrequests_path %>
</p>

and this is the _form that the user puts the request information into:

<%= form_for @vacationrequest do |f| %>
  <% if @vacationrequest.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@vacationrequest.errors.count, "error") %> prohibited this request from being saved: if this continue to happens please email the error to alex@allsafeindustries.com</h2>
      <ul>
      <% @vacationrequest.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :request_name %><br />
    <%= f.text_field :request_name %>
  </div>
  <div class="field">
    <%= f.label :request_date %><br />
    <%= f.text_field :request_date %>
  </div>
  <div class="field">
    <%= f.label :message %><br />
    <%= f.text_area :message %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Finally here are my show and index methods in my controller:

  def index
    @vacationrequests = Vacationrequest.all
    @vacationrequests_by_date = @vacationrequests.group_by(&:request_date)
    @date = params[:date] ? Date.parse(params[:date]) : Date.today
  end

  def show
    @vacationrequest = Vacationrequest.find(params[:id])
  end

Can anybody direct me to what is out of place or why this is nil? Thank you.

In response to the answer here is what I am now getting from the server:

Started POST "/vacationrequests" for 127.0.0.1 at 2012-10-17 20:18:00 -0400
Processing by VacationrequestsController#create as HTML
  Parameters: {"utf8"=>"√", "authenticity_token"=>"E1+xXP0pAIQpwMZruswxIZIrTZB3b
c3NlW3iRv9OLqU=", "vacationrequest"=>{"request_name"=>"One more time", "request_
date"=>"10/31/2012", "message"=>"Lucky number 7?"}, "commit"=>"Create Vacationre
quest"}
  ←[1m←[35m (0.0ms)←[0m  begin transaction
  ←[1m←[36mSQL (15.6ms)←[0m  ←[1mINSERT INTO "vacationrequests" ("created_at", "
message", "request_date", "request_name", "updated_at") VALUES (?, ?, ?, ?, ?)←[
0m  [["created_at", Thu, 18 Oct 2012 00:18:00 UTC +00:00], ["message", "Lucky nu
mber 7?"], ["request_date", nil], ["request_name", "One more time"], ["updated_a
t", Thu, 18 Oct 2012 00:18:00 UTC +00:00]]
  ←[1m←[35m (109.2ms)←[0m  commit transaction
Redirected to http://localhost:3000/vacationrequests/7
Completed 302 Found in 125ms (ActiveRecord: 124.8ms)


Started GET "/vacationrequests/7" for 127.0.0.1 at 2012-10-17 20:18:01 -0400
Processing by VacationrequestsController#show as HTML
  Parameters: {"id"=>"7"}
  ←[1m←[36mVacationrequest Load (0.0ms)←[0m  ←[1mSELECT "vacationrequests".* FRO
M "vacationrequests" WHERE "vacationrequests"."id" = ? LIMIT 1←[0m  [["id", "7"]
]
  Rendered vacationrequests/show.html.erb within layouts/application (15.6ms)
    Completed 500 Internal Server Error in 16ms

ActionView::Template::Error (undefined method `strftime' for nil:NilClass):
    1: <h1><%= @vacationrequest.request_name %></h1>
    2: <%= debug @vacationrequest %>
    3: <p class="info">Requested For <%= @vacationrequest.request_date.strftime(
"%B %e, %Y") %></p>
    4:
    5: <%= simple_format @vacationrequest.message %>
    6:
  app/views/vacationrequests/show.html.erb:3:in `_app_views_vacationrequests_sho
w_html_erb___377763931_36688344'

I also used the view debug and checked my scheme and all of the attributes seemed to line up correctly.

As for the request in the comments here is my Vacationrequest model:

class Vacationrequest < ActiveRecord::Base
  attr_accessible :message, :request_name, :request_date
end

Once again I can't thank you enough for your help.

Here is the schema:

ActiveRecord::Schema.define(:version => 20121016194123) do

  create_table "vacationrequests", :force => true do |t|
    t.string   "request_name"
    t.date     "request_date"
    t.text     "message"
    t.datetime "created_at",   :null => false
    t.datetime "updated_at",   :null => false
  end
end

and the create controller action code:

def create
  @vacationrequest = Vacationrequest.new(params[:vacationrequest])
  if @vacationrequest.save
    redirect_to @vacationrequest, notice: "Created Request!"
  else
    render :new
  end
end

As I'm looking at this, is part of the problem my schema being plural and my controller being singular? Thanks again.

Chris Salzberg
  • 27,099
  • 4
  • 75
  • 82
Alexander
  • 1,577
  • 5
  • 21
  • 35
  • The problem is that `@vacationrequest.request_date` is nil for some reason. Can you post the code for the `Vacationrequest` model? – Chris Salzberg Oct 17 '12 at 21:13
  • I added in the server error output, and checked my schema with the debug attribute information. The model has been added as well. – Alexander Oct 18 '12 at 00:32
  • Sure enough the problem is not happening when you display the record but when you save it. Can you post your db schema and `create` controller action code? – Chris Salzberg Oct 18 '12 at 00:44
  • I added it below the previous edit. I noticed my schema is plural and my controller uses primarily singular syntax. I'm not sure if that make a difference. Thank you again, I really appreciate it. – Alexander Oct 18 '12 at 01:08
  • The plural/singular forms are no problem, that's the convention in rails. I can't see the problem but I'll look a bit more into it later. – Chris Salzberg Oct 18 '12 at 01:33
  • 2
    One thing: you should probably add a validator to your model if you want to make sure that a date is entered when a new record is created. Try adding a line in your `Vacationrequest` model: `validates :request_date, :presence => true` and then try creating a new vacation request. You should get an error. – Chris Salzberg Oct 18 '12 at 01:35
  • I thought it was the convention but I'm still new enough to doubt myself :-) I will gladly add the validator. Thank you. – Alexander Oct 18 '12 at 01:43
  • So I added in the validator and got this error: Request date can't be blank. However in the code above my server is showing the request_date in the POST parameters, so something is failing between the POST and save because if I do Vacationrequest.find(id) I can actually see a Vacationrequest with request_date:nil and everything else saved. Any tips or suggestions would be greatly appreciated I'm going to start searching right now. Thanks again. – Alexander Oct 18 '12 at 13:07

3 Answers3

19

First you have to make sure if there is 'request_date' filled before you create a record by applying ActiveRecord validations.

Secondly, you can use ruby's try method to avoid such exceptions

<%= @vacationrequest.try(:request_date).try(:strftime, '%B %e, %Y') %>

Happy Coding !

Update

In the newer version of Ruby, you can use &. -> lonely operator instead of the solution above. It is also called safe navigation operator.

<%= @vacationrequest&.request_date&.strftime('%B %e, %Y') %>
Shiva
  • 11,485
  • 2
  • 67
  • 84
4

@vacationrequest.request_date is nil, so the record you're looking at is missing the request date. It sounds like you have bad data. In this situation, I'd debug why by:

  1. Dumping the @vacationrequest in the view -- <%= debug @vacationrequest %> (or from your controller: fail @vacationrequest.inspect).
  2. Checking in Rails console (rails c) -- what does Vactionrequest.find(some_id) yield?
  3. Optionally, checking the DB entry.

However you're inputting vacation requests is not saving request dates, so there's probably a bug in your create controller action, model schema, or model validation.

jmdeldin
  • 5,354
  • 1
  • 28
  • 21
  • I ran the console command and this was my output: irb(main):002:0> Vacationrequest.find(3) ←[1m←[35mVacationrequest Load (0.0ms)←[0m SELECT "vacationrequests".* FROM "v acationrequests" WHERE "vacationrequests"."id" = ? LIMIT 1 [["id", 3]] => # – Alexander Oct 18 '12 at 00:35
  • @Alex: Yep, that says `request_date` is nil. How are `Vacationrequest` objects being created and saved? – jmdeldin Oct 18 '12 at 03:36
  • 1
    Also, if you just want to address having a nil, you could do `@vacation_req.try(:strftime, "arguments")`, but it's better to address nil issues in your model or controller (IMO). – jmdeldin Oct 18 '12 at 03:38
  • Absolutely, I don't want it to pass nil as I'm picking the date from date picker and actually want that date to pass through and get saved in request_date. I used try earlier after some research and noticed it didn't fix my problem it just fixed the page load. I'm on my way to work now and I'll add in validators and double check my controller. – Alexander Oct 18 '12 at 10:07
0

Shioyama thank you so much for suggesting this:

validates :request_date, :presence => true

I'm really going to invest the time in learning about the debugging and validation Rails promotes. Because of this I figured out specifically that the datepicker in JQuery wasn't passing through correctly. I went into my assests > javascripts > vacationrequests.js.coffee and found I had left () on the end like this:

jQuery ->
  $('#vacationrequest_request_date').datepicker()
    dateFormat: 'yy-mm-dd'

Once I removed the brackets like this:

jQuery ->
  $('#vacationrequest_request_date').datepicker
    dateFormat: 'yy-mm-dd'

Everything is working, Index, Show, Edit, Update, New. Thank you both for all the suggestions and showing me how to run this down.

Alexander
  • 1,577
  • 5
  • 21
  • 35
  • Wow, nice catch! That's pretty tricky to debug, but definitely figuring out that the problem was in the saving and not in the rendering was important. Coffeescript is elegant but its minimalism can also hide bugs like this one. – Chris Salzberg Oct 18 '12 at 13:52