I have two forms that people need to fill out, an Incident form and a
Timesheet form. I want the Timesheet form to appear right after a user
submits the Incident form.
This is my code for the Incident controller;
if @incident.save
format.html { redirect_to new_timesheet_path(@incident.id) }
After clicking submit, that takes me to this URL (a blank page):
http://localhost:3000/timesheets/new.16
What do I put in the Timesheets controller to make the new Timesheet
form appear, and have it connected to the Incident that was just
submitted?
(Both Incident and Timesheet are top level resources.)
Thanks!
Finne J. wrote in post #968107:
I have two forms that people need to fill out, an Incident form and a
Timesheet form. I want the Timesheet form to appear right after a user
submits the Incident form.
This is my code for the Incident controller;
if @incident.save
format.html { redirect_to new_timesheet_path(@incident.id) }
Bizarre. new_*_path doesn’t normally take an argument (except for an
optional format string, which is why you’re getting the .16 below).
After clicking submit, that takes me to this URL (a blank page):
http://localhost:3000/timesheets/new.16
What does your routes file look like, or the output from rake routes?
What do I put in the Timesheets controller to make the new Timesheet
form appear, and have it connected to the Incident that was just
submitted?
Do you have any associations set up between the Timesheet and Incident
models?
(Both Incident and Timesheet are top level resources.)
Perhaps they shouldn’t be in this case.
Thanks!
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
Marnen Laibow-Koser wrote in post #968112:
Bizarre. new_*_path doesn’t normally take an argument (except for an
optional format string, which is why you’re getting the .16 below).
Is there another way to pass the incident object to the New Timesheet
method? The new Timesheet needs to know it’s supposed to be attached to
the Incident.
What does your routes file look like, or the output from rake routes?
resources :incidents
resources :timesheets
Do you have any associations set up between the Timesheet and Incident
models?
The Incident model has_one :timesheet
(Both Incident and Timesheet are top level resources.)
Perhaps they shouldn’t be in this case.
How can I nest them?
Finne J. wrote in post #968117:
Marnen Laibow-Koser wrote in post #968112:
Bizarre. new_*_path doesn’t normally take an argument (except for an
optional format string, which is why you’re getting the .16 below).
Is there another way to pass the incident object to the New Timesheet
method?
new_timesheet_path goes to TimesheetsController#new , not Timesheet.new
.
The new Timesheet needs to know it’s supposed to be attached to
the Incident.
What does your routes file look like, or the output from rake routes?
resources :incidents
resources :timesheets
Do you have any associations set up between the Timesheet and Incident
models?
The Incident model has_one :timesheet
And Timesheet belongs_to :incident , I hope?
(Both Incident and Timesheet are top level resources.)
Perhaps they shouldn’t be in this case.
How can I nest them?
See the routing documentation. Once you do nest them, you get the
routes you need for free.
If you don’t want to nest them, other solutions are possible, but I’d
advise nesting if it’s feasible for your project.
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
Thank you, I appreciate your help so far, I’ve been struggling with this
for days now.
And Timesheet belongs_to :incident , I hope?
Correct.
See the routing documentation. Once you do nest them, you get the
routes you need for free.
If you don’t want to nest them, other solutions are possible, but I’d
advise nesting if it’s feasible for your project.
Ok, I have nested them like this:
resources :incidents do
resources :timesheets
end
And I changed Incidents#create to this:
if @incident.save
format.html { redirect_to incident_timesheet_url(@incident) }
Is that the ‘free route’ you mentioned?
On a side note, by changing the resources to nested instead of top
level, it broke my Index page which shows a list of Incidents and their
Timesheets. It pointed out this line of code:
<%= link_to ‘View Time Sheet’, timesheet_path(incident) %> |
Finne J. wrote in post #968122:
Thank you, I appreciate your help so far, I’ve been struggling with this
for days now.
And Timesheet belongs_to :incident , I hope?
Correct.
See the routing documentation. Once you do nest them, you get the
routes you need for free.
If you don’t want to nest them, other solutions are possible, but I’d
advise nesting if it’s feasible for your project.
Ok, I have nested them like this:
resources :incidents do
resources :timesheets
end
Something else I just realized. Since Incident :has_one Timesheet, you
probably want a singular resource – resource :timesheet instead of
resources :timesheets . Again, please check the docs rather than taking
my word for it.
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
On a side note, by changing the resources to nested instead of top
level, it broke my Index page which shows a list of Incidents and their
Timesheets. It pointed out this line of code:
<%= link_to ‘View Time Sheet’, timesheet_path(incident) %> |
Right, of course. Run rake routes to see what your routes look like
now.
Ok, I ran ‘rake routes’ and it showed:
incident_timesheet GET /incidents/:incident_id/timesheet(.:format)
{:action=>“show”, :controller=>“timesheets”}
So I changed the code in my Index view to:
<%= link_to ‘View Time Sheet’, incident_timesheet %> |
That triggers: undefined local variable or method `incident_timesheet’
Finne J. wrote in post #968122:
Thank you, I appreciate your help so far, I’ve been struggling with this
for days now.
And Timesheet belongs_to :incident , I hope?
Correct.
See the routing documentation. Once you do nest them, you get the
routes you need for free.
If you don’t want to nest them, other solutions are possible, but I’d
advise nesting if it’s feasible for your project.
Ok, I have nested them like this:
resources :incidents do
resources :timesheets
end
And I changed Incidents#create to this:
if @incident.save
format.html { redirect_to incident_timesheet_url(@incident) }
Is that the ‘free route’ you mentioned?
It’s one of them, yes.
On a side note, by changing the resources to nested instead of top
level, it broke my Index page which shows a list of Incidents and their
Timesheets. It pointed out this line of code:
<%= link_to 'View Time Sheet', timesheet_path(incident) %>
----------------------------
Right, of course. Run rake routes to see what your routes look like
now.
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
Finne J. wrote in post #968131:
On a side note, by changing the resources to nested instead of top
level, it broke my Index page which shows a list of Incidents and their
Timesheets. It pointed out this line of code:
<%= link_to 'View Time Sheet', timesheet_path(incident) %>
----------------------------
Right, of course. Run rake routes to see what your routes look like
now.
Ok, I ran ‘rake routes’ and it showed:
incident_timesheet GET /incidents/:incident_id/timesheet(.:format)
{:action=>“show”, :controller=>“timesheets”}
So I changed the code in my Index view to:
<%= link_to 'View Time Sheet', incident_timesheet %>
---------------------------------
That triggers: undefined local variable or method `incident_timesheet’
Of course. You forgot the _path.
Please go read the routing docs again, paying particular attention to
the autogenerated helpers.
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
Sent from my iPhone
On Dec 13, 2010, at 3:08 PM, Finne J. wrote:
now.
That triggers: undefined local variable or method `incident_timesheet’
–
OK, you’re really close. However, think about that route. It needs
an :incident_id and you haven’t given one. For the create, you’ll
want to do incident_timesheet_path(incident)
-Rob
Rob B.
[email protected] http://AgileConsultingLLC.com/
[email protected] http://GaslightSoftware.com/
Finne J. wrote in post #968154:
OK, you’re really close. However, think about that route. It needs
an :incident_id and you haven’t given one. For the create, you’ll
want to do incident_timesheet_path(incident)
Thank you, I realized that as well and put the (incident) parameter:
<%= link_to 'View Time Sheet', incident_timesheet_path(incident)
%>
When I click on the View Timesheet link in the Index, I get:
undefined method `edit_timesheet_path’
Which has to do with this line in timesheets/show.html.erb:
<%= link_to ‘Edit’, edit_timesheet_path %>
Am I referencing this edit path correctly?
Instead of asking us, look at your rake routes output again! That’s why
it’s there.
As per your advice I will go ahead and read the whole Routing
documentation from front to back again because I think this will keep
coming up as I adjust the rest of the code I already had.
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
Instead of asking us, look at your rake routes output again! That’s why
it’s there.
Thanks, I just did and realized what I had to change.
With these nested resources in place, do I still have to set @timesheet
in TimesheetsController#show?
This is what I had before:
def show
@timesheet = current_user.timesheets.find(params[:id])
The reason I’m asking is because in timehsheets/show.html.erb I have:
Date:
<%= timesheet.date %>
-------------------------
which is not working (undefined local variable or method `timesheet'). I
just want to retrieve the value for 'date' in the database timesheet
table..
OK, you’re really close. However, think about that route. It needs
an :incident_id and you haven’t given one. For the create, you’ll
want to do incident_timesheet_path(incident)
Thank you, I realized that as well and put the (incident) parameter:
<%= link_to 'View Time Sheet', incident_timesheet_path(incident)
%> |
When I click on the View Timesheet link in the Index, I get:
undefined method `edit_timesheet_path’
Which has to do with this line in timesheets/show.html.erb:
<%= link_to ‘Edit’, edit_timesheet_path %>
Am I referencing this edit path correctly?
As per your advice I will go ahead and read the whole Routing
documentation from front to back again because I think this will keep
coming up as I adjust the rest of the code I already had.
Finne J. wrote in post #968340:
Instead of asking us, look at your rake routes output again! That’s why
it’s there.
Thanks, I just did and realized what I had to change.
With these nested resources in place, do I still have to set @timesheet
in TimesheetsController#show?
Of course. Changing routes.rb only changes the routing, nothing else.
You may want to use a plugin such as make_resourceful to abstract some
of this.
This is what I had before:
def show
@timesheet = current_user.timesheets.find(params[:id])
Why the current_user part? Just Timesheet.find(params[:id]) should do
the trick – after all, the ID is unique.
The reason I’m asking is because in timehsheets/show.html.erb I have:
Date:
<%= timesheet.date %>
-------------------------
which is not working (undefined local variable or method `timesheet'). I
just want to retrieve the value for 'date' in the database timesheet
table..
Of course that’s not working. You haven’t defined timesheet anywhere.
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
On 14 December 2010 17:39, Finne J. [email protected] wrote:
Of course that’s not working. You haven’t defined timesheet anywhere.
@timesheet = Timesheet.find(params[:id])
Seems to be not working… Does it even need to find by ID if I’m
already using the incident_timesheet_path(incident) link?
All the link does is build a URL for you with appropriate params. In
the controller action you then have to do things with the params.
Have a look in log/development.log and you will see what params are
being passed. Also I suggest having a look at the Rails Guide on
debugging. You can then use ruby-debug to break into your code before
the find call you have shown and inspect params to see what is there
and work out why the find is not working. You can also experiment
then calling find from the console to see what works.
Colin
Why the current_user part? Just Timesheet.find(params[:id]) should do
the trick – after all, the ID is unique.
I read in Beginning Rails 3 that current_user makes sure that the logged
in user can not see other people’s incidents/timesheets. I have the same
thing in the IncidentsController:
def index
@incidents = current_user.incidents.all
But now that Timesheets are nested within Incidents, I don’t have to
have current_user for that I guess.
Of course that’s not working. You haven’t defined timesheet anywhere.
@timesheet = Timesheet.find(params[:id])
Seems to be not working… Does it even need to find by ID if I’m
already using the incident_timesheet_path(incident) link?
No, I’m sure it’s working fine. But you’re defining @timesheet in your
controller, then calling timesheet (without the @) in the view.
Got it, I changed it back to @timesheet.
Does it even need to find by ID if I’m
already using the incident_timesheet_path(incident) link?
Yes. That only passes the ID. HTTP has no means of passing
ActiveRecord objects around.
Ok, thanks for the development log tip! I wasn’t aware of it.
I now use the incident_id to set @timesheet like this:
@timesheet = Incident.find(params[:incident_id]).timesheet
And it looks like it’s working!
I wasn’t aware of authorization plugins, I just used the technique that
the Beginning Rails 3 book used. I’ll do some research on auth plugins
Finne J. wrote in post #968357:
Why the current_user part? Just Timesheet.find(params[:id]) should do
the trick – after all, the ID is unique.
I read in Beginning Rails 3 that current_user makes sure that the logged
in user can not see other people’s incidents/timesheets.
True enough, though I’d probably use an authorization plugin for that.
I have the same
thing in the IncidentsController:
def index
@incidents = current_user.incidents.all
But now that Timesheets are nested within Incidents, I don’t have to
have current_user for that I guess.
Of course that’s not working. You haven’t defined timesheet anywhere.
@timesheet = Timesheet.find(params[:id])
Seems to be not working…
No, I’m sure it’s working fine. But you’re defining @timesheet in your
controller, then calling timesheet (without the @) in the view.
Does it even need to find by ID if I’m
already using the incident_timesheet_path(incident) link?
Yes. That only passes the ID. HTTP has no means of passing
ActiveRecord objects around.
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
Sent from my iPhone
Colin L. wrote in post #968413:
On 14 December 2010 18:44, Finne J. [email protected] wrote:
Ok, thanks for the development log tip! I wasn’t aware of it.
I now use the incident_id to set @timesheet like this:
@timesheet = Incident.find(params[:incident_id]).timesheet
And it looks like it’s working!
Great. Do have a go with ruby-debug too. You should not need it
often but sometimes when you just cannot understand what is going on
then it is invaluable.
Colin
I definitely will! Many thanks for taking the time to help me with all
this, I really appreciate it 
Just another quick question if you don’t mind.
I’m trying to manually append a SafetyOfficer to the Timesheet with the
Rails console:
Incident.first.timesheet.safety_officer << SafetyOfficer.last
NoMethodError: You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.<<
I’m searching for a solution but can’t find anything. Do you know what
this error message means? All the fields in the SafetyOfficer.last
object are correct (only ‘timesheet_id’ is nil).