Why is id off by one or defined different in edit vs in update?

11 views
Skip to first unread message

Robert Phillips

unread,
Jun 8, 2018, 3:54:31 PM6/8/18
to Ruby on Rails: Talk
why is id off by one or defined different in edit vs in update? I will explain what I mean

I have a controller called Bottles and a model Bottle

My config\routes.rb file has the line- resources :bottles

I have this controller

class BottlesController < ApplicationController
  def index
  end

  def show
  end

  def edit
    # http://127.0.0.1:3000/bottles/0/edit       :id==0
    
    # <ActionController::Parameters {"controller"=>"bottles", "action"=>"edit", "id"=>"0"} permitted: false>
    
# Bottle.all[0] gives <Bottle id: 1, name: "tod", size: 234,...>
   
    @bottle=Bottle.all[params[:id].to_i]   #:id==0
  end


I have these views

C:\rubytest\testoby>type app\views\bottles\new.html.erb
<%= form_for @bottle do |f| %>
<%= f.text_field :name %>
<%= f.text_field :size %>
<%= f.submit “Create” %>
<% end %>

C:\rubytest\testoby>type app\views\bottles\edit.html.erb
<%= form_for @bottle do |f| %>
<%= f.text_field :name %>
<%= f.text_field :size %>
<%= f.submit “Save” %>
<% end %>
C:\rubytest\testoby>

I went to http://127.0.0.1:3000/bottles/new and I made a bottle

name- tod
size- 234


I then go to http://127.0.0.1:3000/bottles/0/edit

and I see the bottle there in the form

I then change tod to todd and click ‘save’


here’s the weird thing


I see the URL change to

http://127.0.0.1:3000/bottles/1


but i’d expect it to change to

http://127.0.0.1:3000/bottles/0


I’d expect the form to be submitted to /bottles/0 but it’s not, it’s submitted to /bottles/1


And the params have :id=1


So when it comes to my update, I have to write this line in the controller, subtracting 1 from the id


@abottle=Bottle.all[params[:id].to_i-1]


I can see that there is a difference of definition of :id that one could use… The id in the URL could be either 

A)The index in the array e.g. Bottle.all[params[:id]] (Which is what i’ve got for the edit action). or 

B) The id attribute of the object, (Which is what i’ve got for the update action @abottle=Bottle.all[params[:id].to_i-1]


One could say, it’s 'A', the URL. But then why should the update URL have an :id that is one up from the ID in the edit URL?


Thanks

Hassan Schroeder

unread,
Jun 8, 2018, 6:03:51 PM6/8/18
to rubyonrails-talk
On Fri, Jun 8, 2018 at 12:54 PM, Robert Phillips
<robert.p...@gmail.com> wrote:

> def edit
> # http://127.0.0.1:3000/bottles/0/edit :id==0

Where in the world are you getting this id of 0 ? What database
are you using? Every DB I've worked with starts an auto-increment
sequence with a positive (e.g. 1 or higher) number...

--
Hassan Schroeder ------------------------ hassan.s...@gmail.com
twitter: @hassan
Consulting Availability : Silicon Valley or remote

Robert Phillips

unread,
Jun 8, 2018, 8:23:09 PM6/8/18
to Ruby on Rails: Talk


On Friday, 8 June 2018 23:03:51 UTC+1, Hassan Schroeder wrote:
On Fri, Jun 8, 2018 at 12:54 PM, Robert Phillips
<robert.p...@gmail.com> wrote:

>   def edit
>     # http://127.0.0.1:3000/bottles/0/edit       :id==0

Where in the world are you getting this id of 0 ? What database
are you using? Every DB I've worked with starts an auto-increment
sequence with a positive (e.g. 1 or higher) number...



Thanks, well spotted, that was my mistake / the bug in my program.

The id of the object was 1.  But I was going to /bottles/0/edit   Then in the edit action I was using that number (0),  to identify the object, because I was using that number as an index to the array.   Bottles.all[0] So the data from the first bottle was going into the form.  

Then, when I click the button to submit the form,  it  posts to /bottles/1  because it was using the id of @bottle

So I need my edit action to treat the number in the url (the id), as an id and not as an index to an array.

So , in the edit action, I could use @bottle=Bottle.find(...), and then pass in the id to the find method.

So the id in the edit url will then match the id of the object, and then there's no change in id when the form is submitted.

Thanks

Jim Ruther Nill

unread,
Jun 8, 2018, 9:43:13 PM6/8/18
to rubyonra...@googlegroups.com
On Sat, Jun 9, 2018 at 5:54 AM, Robert Phillips <robert.p...@gmail.com> wrote:
why is id off by one or defined different in edit vs in update? I will explain what I mean

I have a controller called Bottles and a model Bottle

My config\routes.rb file has the line- resources :bottles

I have this controller

class BottlesController < ApplicationController
  def index
  end

  def show
  end

  def edit
    # http://127.0.0.1:3000/bottles/0/edit       :id==0
    
    # <ActionController::Parameters {"controller"=>"bottles", "action"=>"edit", "id"=>"0"} permitted: false>
    
# Bottle.all[0] gives <Bottle id: 1, name: "tod", size: 234,...>
   
    @bottle=Bottle.all[params[:id].to_i]   #:id==0

Your error is on these lines.  When working on arrays, the first item in an array has an index of 0.  So you'd think that

bottles = Bottle.all
bottles[0].id == 1
bottles[1].id == 2

and so on.

In the edit action, you should be getting the id of the bottle so you can find the bottle using

Bottle.find(params[:id])
 
  end


I have these views

C:\rubytest\testoby>type app\views\bottles\new.html.erb
<%= form_for @bottle do |f| %>
<%= f.text_field :name %>
<%= f.text_field :size %>
<%= f.submit “Create” %>
<% end %>

C:\rubytest\testoby>type app\views\bottles\edit.html.erb
<%= form_for @bottle do |f| %>
<%= f.text_field :name %>
<%= f.text_field :size %>
<%= f.submit “Save” %>
<% end %>
C:\rubytest\testoby>

For some weird reason, @bottle here should be defined in the edit action in your controller.  But your
edit action is empty.
 

I went to http://127.0.0.1:3000/bottles/new and I made a bottle

name- tod
size- 234


I then go to http://127.0.0.1:3000/bottles/0/edit

Don't use the index as the number but the actual id saved in the database 

and I see the bottle there in the form

I then change tod to todd and click ‘save’


here’s the weird thing


I see the URL change to

http://127.0.0.1:3000/bottles/1


but i’d expect it to change to

http://127.0.0.1:3000/bottles/0


I’d expect the form to be submitted to /bottles/0 but it’s not, it’s submitted to /bottles/1


And the params have :id=1


So when it comes to my update, I have to write this line in the controller, subtracting 1 from the id


@abottle=Bottle.all[params[:id].to_i-1]


I can see that there is a difference of definition of :id that one could use… The id in the URL could be either 

A)The index in the array e.g. Bottle.all[params[:id]] (Which is what i’ve got for the edit action). or 

B) The id attribute of the object, (Which is what i’ve got for the update action @abottle=Bottle.all[params[:id].to_i-1]


One could say, it’s 'A', the URL. But then why should the update URL have an :id that is one up from the ID in the edit URL?


Thanks

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe@googlegroups.com.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/3e864d52-d02b-4aa4-9839-ba550b472fb0%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
-------------------------------------------------------------
visit my blog at http://jimlabs.herokuapp.com

Robert Phillips

unread,
Jun 9, 2018, 12:10:51 AM6/9/18
to Ruby on Rails: Talk


On Saturday, 9 June 2018 02:43:13 UTC+1, jim wrote:

<snip>   
    @bottle=Bottle.all[params[:id].to_i]   #:id==0

Your error is on these lines.  ..<snip>


Yeah I got it now, thanks, I fixed all my actions


In the edit action, you should be getting the id of the bottle so you can find the bottle using

Bottle.find(params[:id])

yeah


For some weird reason, @bottle here should be defined in the edit action in your controller.  But your
edit action is empty.

actually my edit action wasn't empty, it had one line.   @bottle=Bottle.all[params[:id].to_i]     But I have fixed that now , to a line that uses the .find method Bottle.find(params[:id])   and i've fixed the other actions too, like  update.

Thanks 
Reply all
Reply to author
Forward
0 new messages