# How to do save\_or\_update with ActiveRecords?

**URL:** <https://www.ruby-forum.com/t/how-to-do-save-or-update-with-activerecords/176845>\
**Category:** Rails\
**Created:** [October 7, 2009, 12:47am UTC](https://www.ruby-forum.com/t/how-to-do-save-or-update-with-activerecords/176845 "2009-10-07T00:47:55Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bjoern](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/46a35a/32.png) [@Bjoern](https://www.ruby-forum.com/u/Bjoern)\
**Post date:** [October 7, 2009, 12:47am UTC](https://www.ruby-forum.com/t/how-to-do-save-or-update-with-activerecords/176845/1 "2009-10-07T00:47:55Z")

</div>

Hi,

I am trying to save return values from the Twitter API, so for example  
I have created a model for DirectMessages and Users.

A direct message from Twitter contains a sender and recipient as  
nested hashes.

I want to save these objects using the id from Twitter, too.

I convert the hash to models like this:

def convert\_direct\_message\_hash\_to\_model(dm)  
dm[“sender”] = User.new(dm[“sender”]){|sender| sender.id = dm  
[“sender”][“id”]}  
dm[“recipient”] = User.new(dm[“recipient”]) {|recipient| recipient.id  
= dm[“recipient”][“id”]}  
DirectMessage.new(dm) {|r| r.id = dm[“id”]}  
end

then, if I try dm.save! with a self-sent message (so recipient =  
sender), I get an SQL error, because user id should be unique. It  
seems in this case ActiveRecord attempts to save the objects with an  
INSERT statement.

Is there a way to make it update the record if the object already  
exists in the db, and otherwise create it?

Also other comments to my approach are welcome, as I am fairly new to  
Rails.

Thanks!

Björn

I get the error

---

<div class="post-metadata">

**Author:** ![Bjoern](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/46a35a/32.png) [@Bjoern](https://www.ruby-forum.com/u/Bjoern)\
**Post date:** [October 7, 2009, 12:56am UTC](https://www.ruby-forum.com/t/how-to-do-save-or-update-with-activerecords/176845/2 "2009-10-07T00:56:42Z")

</div>

On Oct 6, 11:46 pm, Bjoern [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> then, if I try dm.save! with a self-sent message (so recipient =  
> sender), I get an SQL error, because user id should be unique. It  
> seems in this case ActiveRecord attempts to save the objects with an  
> INSERT statement.
> 
> Is there a way to make it update the record if the object already  
> exists in the db, and otherwise create it?

If that’s what you want then you should attempt to load the  
appropriate object first, create a new one if you can’t find one and  
then save (see also the dynamic finders -

> **[ActiveRecord::Base](https://api.rubyonrails.org/classes/ActiveRecord/Base.html)**
>
> Active Record Active Record objects don't specify their attributes directly, but rather infer them from the table definition with which they're linked.

)

Fred

---

<div class="post-metadata">

**Author:** ![Bjoern](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/46a35a/32.png) [@Bjoern](https://www.ruby-forum.com/u/Bjoern)\
**Post date:** [October 7, 2009, 2:49am UTC](https://www.ruby-forum.com/t/how-to-do-save-or-update-with-activerecords/176845/3 "2009-10-07T02:49:04Z")

</div>

> > Is there a way to make it update the record if the object already  
> > exists in the db, and otherwise create it?
> 
> If that’s what you want then you should attempt to load the  
> appropriate object first, create a new one if you can’t find one and  
> then save (see also the dynamic finders -[ActiveRecord::Base](http://api.rubyonrails.org/classes/ActiveRecord/Base.html)  
> )

Difficult, since the association seems to be saved automatically. I  
guess I have to switch that off somehow, then. No other way available?

---

<div class="post-metadata">

**Author:** ![Bjoern](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/46a35a/32.png) [@Bjoern](https://www.ruby-forum.com/u/Bjoern)\
**Post date:** [October 7, 2009, 11:24am UTC](https://www.ruby-forum.com/t/how-to-do-save-or-update-with-activerecords/176845/4 "2009-10-07T11:24:14Z")

</div>

> I’m not quite sure what you’re saying. Instead of doing User.new, try  
> to find an appropriate User record first.

I’d like to avoid that, to keep the part of the code clean from  
database access. I create a DirectMessage with two associated Users  
and then only call DirectMessage.save

I suppose I could check all the Users before doing the save, but it  
would create a lot of clutter (compared to one line of executing  
save). I was hoping there would be a more elegant way.

The API docs for save sound as if they would create or update, so  
maybe the question is how do they decide what is new and what needs  
updating.

---

<div class="post-metadata">

**Author:** ![Bjoern](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/46a35a/32.png) [@Bjoern](https://www.ruby-forum.com/u/Bjoern)\
**Post date:** [October 7, 2009, 10:03am UTC](https://www.ruby-forum.com/t/how-to-do-save-or-update-with-activerecords/176845/5 "2009-10-07T10:03:27Z")

</div>

On Oct 7, 1:47 am, Bjoern [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> guess I have to switch that off somehow, then. No other way available?  
> I’m not quite sure what you’re saying. Instead of doing User.new, try  
> to find an appropriate User record first.

Fred

---

<div class="post-metadata">

**Author:** ![Bjoern](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/46a35a/32.png) [@Bjoern](https://www.ruby-forum.com/u/Bjoern)\
**Post date:** [October 7, 2009, 3:44pm UTC](https://www.ruby-forum.com/t/how-to-do-save-or-update-with-activerecords/176845/6 "2009-10-07T15:44:10Z")

</div>

On Oct 7, 11:52 am, Frederick C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> If you do User.new you will always get a new object that AR will then  
> try to insert.

Any other options?

> Sounds like you would also get an error whenever you handle a message  
> to / from a user you have already handled a message from.

True - so far I only tested it from unit tests, so I guess there was  
nothing else in the db.

---

<div class="post-metadata">

**Author:** ![Bjoern](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/46a35a/32.png) [@Bjoern](https://www.ruby-forum.com/u/Bjoern)\
**Post date:** [October 7, 2009, 11:53am UTC](https://www.ruby-forum.com/t/how-to-do-save-or-update-with-activerecords/176845/7 "2009-10-07T11:53:31Z")

</div>

On Oct 7, 10:22 am, Bjoern [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> The API docs for save sound as if they would create or update, so  
> maybe the question is how do they decide what is new and what needs  
> updating.

If you do User.new you will always get a new object that AR will then  
try to insert.

Sounds like you would also get an error whenever you handle a message  
to / from a user you have already handled a message from.

Fred

---

<div class="post-metadata">

**Author:** ![Bjoern](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/46a35a/32.png) [@Bjoern](https://www.ruby-forum.com/u/Bjoern)\
**Post date:** [October 8, 2009, 10:03am UTC](https://www.ruby-forum.com/t/how-to-do-save-or-update-with-activerecords/176845/8 "2009-10-08T10:03:01Z")

</div>

On Oct 7, 2:42 pm, Bjoern [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Oct 7, 11:52 am, Frederick C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> wrote:
> 
> > If you do User.new you will always get a new object that AR will then  
> > try to insert.
> 
> Any other options?

I think you just need to bite the bullet and find the record first.  
having a neat one liner is one thing but only if it actually works.  
You could hack around and fool activerecord into thinking the record  
isn’t new even though you’ve just called User.new but you’d probably  
just be storing up trouble for later and increasing the chances that  
your code breaks with a later version of rails.

Fred
