# Updating records

**URL:** <https://www.ruby-forum.com/t/updating-records/185962>\
**Category:** Rails\
**Created:** [March 29, 2010, 8:00pm UTC](https://www.ruby-forum.com/t/updating-records/185962 "2010-03-29T20:00:53Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![xman2000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/9d8465/32.png) [@xman2000](https://www.ruby-forum.com/u/xman2000)\
**Post date:** [March 29, 2010, 8:00pm UTC](https://www.ruby-forum.com/t/updating-records/185962/1 "2010-03-29T20:00:53Z")

</div>

So I would like to be able to update a record without having to load the  
edit page. Lets use checking out a book as an example. From the front  
page of my application I would like to be able to have a form field  
where I can enter a record id and select one of a couple of check boxes  
and then hit submit which will update the associated record with the  
action selected by the check box (check out, check in, etc). I am  
assuming I need to use a form\_tag but I am not sure how to go about  
writing the controller and I am assuming I will need to do some custom  
routing.

def update

```
@barcode = params[:barcode]
@checkout = params[:checkout]

@book = Book.find(:first, :conditions => {:barcode => [@barcode]})

@book.update_attributes(params[:book])

```

end

---

<div class="post-metadata">

**Author:** ![xman2000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/9d8465/32.png) [@xman2000](https://www.ruby-forum.com/u/xman2000)\
**Post date:** [March 29, 2010, 10:10pm UTC](https://www.ruby-forum.com/t/updating-records/185962/2 "2010-03-29T22:10:28Z")

</div>

On 29 March 2010 19:00, Stephen N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> def update
> 
> @barcode = params[:barcode]  
> @checkout = params[:checkout]
> 
> @book = Book.find(:first, :conditions =\> {:barcode =\> [@barcode]})
> 
> @book.update\_attributes(params[:book])
> 
> end

Just use the same technique as on the edit page but miss out the  
fields that you do not wish to change. Then submit to the existing  
update action, you do not need to change it as update\_attributes only  
changes the fields that are provided, and leaves the others unchanged  
(I think that is correct, someone will correct me if I am wrong).  
Depending on how similar the required view is to the normal edit view  
you may even be able to use the same one, just hiding the fields you  
do not want.

By the way form\_for is the conventional way now, rather than form\_tag.  
Your edit view will likely be using that unless you picked up the  
code from an old tutorial or book.

Colin

---

<div class="post-metadata">

**Author:** ![xman2000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/9d8465/32.png) [@xman2000](https://www.ruby-forum.com/u/xman2000)\
**Post date:** [March 29, 2010, 10:44pm UTC](https://www.ruby-forum.com/t/updating-records/185962/3 "2010-03-29T22:44:47Z")

</div>

Hmm, I understand what you are saying, and that is indeed what I tried  
to do originally but because I am not loading the edit page first I am  
pretty sure I cannot use the form\_for method. The form\_tag that I am  
using appears to parse the fields correctly however the data is not  
being processed correctly on the backend…

Parameters: {“commit”=\>“Update”, “action”=\>“update”,  
“barcode”=\>“123456789”, “checkout”=\>“1”, “controller”=\>“books”}

I am able to type the barcode in and hit update but I am being taken to  
the update page rather than just processing the update method. I know  
it is reading the hash correctly because if I change the barcode I am  
getting a nil value error. Like you said, my form is simple (this is in  
my index.erb.html file),

\<% form\_tag(:action =\> “update”) do -%\>

 Process Return Barcode\<%= text\_field\_tag 'barcode' %\>  
 Check Out?\<%= check\_box\_tag 'checkout' %\> 

\<%= submit\_tag "Update" %\>

\<% end -%\>

You have already seen my controller; there isn’t much here so I must be  
doing something pretty stupid… Thanks,

Colin L. wrote:

> On 29 March 2010 19:00, Stephen N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > ï¿½def update
> > 
> > ï¿½ ï¿½@barcode = params[:barcode]  
> > ï¿½ ï¿½@checkout = params[:checkout]
> > 
> > ï¿½ ï¿½@book = Book.find(:first, :conditions =\> {:barcode =\> [@barcode]})
> > 
> > ï¿½ ï¿½@book.update\_attributes(params[:book])
> > 
> > ï¿½end
> 
> Just use the same technique as on the edit page but miss out the  
> fields that you do not wish to change. Then submit to the existing  
> update action, you do not need to change it as update\_attributes only  
> changes the fields that are provided, and leaves the others unchanged  
> (I think that is correct, someone will correct me if I am wrong).  
> Depending on how similar the required view is to the normal edit view  
> you may even be able to use the same one, just hiding the fields you  
> do not want.
> 
> By the way form\_for is the conventional way now, rather than form\_tag.  
> Your edit view will likely be using that unless you picked up the  
> code from an old tutorial or book.
> 
> Colin

---

<div class="post-metadata">

**Author:** ![xman2000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/9d8465/32.png) [@xman2000](https://www.ruby-forum.com/u/xman2000)\
**Post date:** [March 30, 2010, 8:20pm UTC](https://www.ruby-forum.com/t/updating-records/185962/4 "2010-03-30T20:20:45Z")

</div>

I switched over to form\_for as you suggested and that seems to be  
working much better but I am still running into a problem. The form  
appears to be submitting the correct data but I am having a problem with  
selecting the record correctly. Specifically, in my controller,

def update

```
@book = Book.find(:first, :conditions => ["barcode = 

```

?",params[:barcode]])

```
@book.update_attributes(params[:book])
redirect_to "/books"

```

end

If I replace the params[:barcode] with a real barcode (e.g.  
Book.find(:first, :conditions =\> {‘barcode’ =\> [‘123456789’]})) number  
the form processes successfully and updates my database. When I try  
from the form however I am getting a null value error even though I can  
see the parameters being passed along in the logs so I am not sure why  
they are not available to the model…

Processing BooksController#update (for 10.0.1.65 at 2010-03-30 14:01:07)  
[POST]  
Parameters: {“commit”=\>“Update”, “action”=\>“update”,  
“authenticity\_token”=\>“vq6j9DJ57+AP4kbdbFHjeqeXHiYJDr9RT+zwHVCJ7mI=”,  
“book”=\>{“bounceback”=\>“1”, “barcode”=\>“123456789”},  
“controller”=\>“books”}

[4;36;1mBook Load (0.6ms)[0m [0;1mSELECT \* FROM `books` WHERE (barcode  
= NULL) LIMIT 1[0m

I have tried every combination of :conditions I can think of but I don’t  
seem to be able to get it to work correctly. Thanks!

Stephen

Colin L. wrote:

> On 29 March 2010 21:44, Stephen N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > the update page rather than just processing the update method. Â I know
> > 
> > Â \<%= submit\_tag "Update" %\>
> > 
> > \<% end -%\>
> 
> As I said it is easier to use the form\_for method. Just copy the  
> existing edit view code (which presumably includes the barcode and  
> checkout values) and remove from the form the fields that you do not  
> want.
> 
> The problem with the submit is that you are not putting the data in  
> the params correctly. Try doing an edit and look in development.log  
> to see what the params are, then do the same with yours and compare  
> them. Your fields should be inside a hash for the complete object.  
> But as I said if you use form\_for it will all be done for you. I  
> don’t understand what problem you are having with form\_for, what has  
> it got to do with loading the edit page? You are using your new page  
> instead of the edit page in this case.
> 
> Colin

---

<div class="post-metadata">

**Author:** ![xman2000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/9d8465/32.png) [@xman2000](https://www.ruby-forum.com/u/xman2000)\
**Post date:** [March 30, 2010, 10:21pm UTC](https://www.ruby-forum.com/t/updating-records/185962/5 "2010-03-30T22:21:06Z")

</div>

On 30 March 2010 19:20, Stephen N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> @book.update\_attributes(params[:book])
> 
> Processing BooksController#update (for 10.0.1.65 at 2010-03-30 14:01:07)  
> [POST]  
> Parameters: {“commit”=\>“Update”, “action”=\>“update”,  
> “authenticity\_token”=\>“vq6j9DJ57+AP4kbdbFHjeqeXHiYJDr9RT+zwHVCJ7mI=”,  
> “book”=\>{“bounceback”=\>“1”, “barcode”=\>“123456789”},  
> “controller”=\>“books”}

Look carefully at the params, you will see that you want  
params[:book][:barcode] in your find.

You could have found this by using ruby-debug to break into your  
controller where it is failing and inspecting the variables. See the  
guide on debugging.

I would have expected to see an id there also, are you not passing the  
record up to the view where the form\_for is? Look at the code in the  
controller#edit and view#edit and copy those except for missing out  
the fields that you don’t want in the view. Then you should get the  
id also and can lookup on that rather than the barcode, which would be  
more conventional. Unless I am misunderstanding exactly what you are  
doing (which would not be unusual).

By the way, could you not ‘top post’ it would make it easier to follow  
the thread. Thanks.

Colin

---

<div class="post-metadata">

**Author:** ![xman2000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/9d8465/32.png) [@xman2000](https://www.ruby-forum.com/u/xman2000)\
**Post date:** [March 31, 2010, 9:12pm UTC](https://www.ruby-forum.com/t/updating-records/185962/6 "2010-03-31T21:12:08Z")

</div>

Colin L. wrote:

> On 30 March 2010 19:20, Stephen N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > ï¿½ ï¿½@book.update\_attributes(params[:book])
> > 
> > Processing BooksController#update (for 10.0.1.65 at 2010-03-30 14:01:07)  
> > [POST]  
> > ï¿½Parameters: {“commit”=\>“Update”, “action”=\>“update”,  
> > “authenticity\_token”=\>“vq6j9DJ57+AP4kbdbFHjeqeXHiYJDr9RT+zwHVCJ7mI=”,  
> > “book”=\>{“bounceback”=\>“1”, “barcode”=\>“123456789”},  
> > “controller”=\>“books”}
> 
> Look carefully at the params, you will see that you want  
> params[:book][:barcode] in your find.
> 
> You could have found this by using ruby-debug to break into your  
> controller where it is failing and inspecting the variables. See the  
> guide on debugging.
> 
> I would have expected to see an id there also, are you not passing the  
> record up to the view where the form\_for is? Look at the code in the  
> controller#edit and view#edit and copy those except for missing out  
> the fields that you don’t want in the view. Then you should get the  
> id also and can lookup on that rather than the barcode, which would be  
> more conventional. Unless I am misunderstanding exactly what you are  
> doing (which would not be unusual).
> 
> By the way, could you not ‘top post’ it would make it easier to follow  
> the thread. Thanks.
> 
> Colin

That worked great; I will post the final controller in case anyone else  
wants to do it but that is pretty cool. I am not using the key field  
because the form is on the index page - not the edit page - which means  
the record hasn’t actually been selected at that point. The barcode  
field is unique but not the key field because I need to be able to store  
alphanumeric information as part of the barcode and the id field is an  
integer. While not necessarily in the spirit of ruby, doing this allows  
me to arbitrarily update any record in the database from anywhere in my  
application regardless of any nesting or other model complexities.  
Thanks for the help, just a couple more problems and my first real app  
will be done!

---

<div class="post-metadata">

**Author:** ![xman2000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/9d8465/32.png) [@xman2000](https://www.ruby-forum.com/u/xman2000)\
**Post date:** [March 30, 2010, 9:29am UTC](https://www.ruby-forum.com/t/updating-records/185962/7 "2010-03-30T09:29:57Z")

</div>

On 29 March 2010 21:44, Stephen N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> the update page rather than just processing the update method. Â I know
> 
> Â \<%= submit\_tag "Update" %\>
> 
> \<% end -%\>

As I said it is easier to use the form\_for method. Just copy the  
existing edit view code (which presumably includes the barcode and  
checkout values) and remove from the form the fields that you do not  
want.

The problem with the submit is that you are not putting the data in  
the params correctly. Try doing an edit and look in development.log  
to see what the params are, then do the same with yours and compare  
them. Your fields should be inside a hash for the complete object.  
But as I said if you use form\_for it will all be done for you. I  
don’t understand what problem you are having with form\_for, what has  
it got to do with loading the edit page? You are using your new page  
instead of the edit page in this case.

Colin
