Jordi had the solution, the id is updated on save/save!, just call the
property you want from your model.
Just to set the record straight, that was my first suggestion, too. Just look! Since that only works when you were the one creating that last record, I also noted the other possibility. The OP's question sounded like the simple mymodel.id would work, but that's such an obvious thing (for *me*) that I offered something that might not have been obvious.
Using MyModel.maximum('id') to find the last inserted id is really not a
good idea. The reason is that you can NEVER ensure that there wasn't
another insert into your database in between your model.save! and
MyModel.maximum('id') calls no matter how short the time frame in
between them.
So this is not a good practice at all.
Hope this helps.
I don't recall if the OP (Rudy?) has chimed back into the discussion, but it would help if he clarified how/if this has helped.
Hi guys, thanks for all the help. Greatly appriciated. It did clarify
it. What I use now (and tell me please if this is wrong for any
reason) is
car=Car.create!(:make => foo)
after that, car.id is indeed the id from the newly inserted
record.
In a way, once you know, it seems so obvious, and it was stated
somewhere in the Agile Web Development book as well. (p310) But it was
hard to find - as usual for me.
I hope that, by having it written out here, as you guys so greatly
did, anyone looking for the answer on this question can now find it
here as well. This discussiongroup can not be praisedf enough!
Rudy
after that, car.id is indeed the id from the newly inserted
record.
Someone here doesn't remember the Bad Old Days...
- you had to research how to query that freaking ID correctly
- you had to research AGAIN to figure out how to find it
for each type of database you use
- you had to research _AGAIN_ to make sure the number
didn't change when you went to different database
connections and/or threads
- you had to give up and re-query the record you just wrote
back out of the database, just to robustly get its ID
When someone scarred by all those experiences tries to use
ActiveRecord, and the documentation doesn't exactly say "the correct
id always pops into your database record when the wind blows", you
tend to forget how lean and creative all your database activities can
be!
We do that one in tests to find the last-added record.
Maybe I'm paranoid,
Maybe you are test-infected? (-;
but doesn't that run the risk of a different row
getting created before you can do that?
Yes. I just thought of a fix:
record = assert_latest Record do
get :create_record, :value => 'foo'
end
assert_equal 'foo', record.value
If we assume monotonic IDs, we can implement that by fetching Record.maximum(id) before the block, then fetching Record.find_by_id(id + 1) after the block. Now we know we have the first new Record which our tested code created. That's probably more robust, and test-isolating, than fetching the very last record!
I think I'l go write that one and retrofit it into a few places...
OR, easier than all that, drop the database / tables in between tests
and use migrations / fixtures to 'build them up' again when ready. May
add a bit of overhead to you timing for execution but it will reset all
the internal counters in the DB and you'll always restart at '1'. (Or
whatever you set minimum is).
Occurs to me that many of our projects have a "super-test" Rake task
to rebuild the database just like that.
So, no 4-billionth test run bug (or award) for us!
record = assert_latest Record do
get :create_record, :value => 'foo'
end
assert_equal 'foo', record.value
And now if one slips in behind you, you can have a valid record that
fails that test
That's why we run the tests every few edits. The faster they go, the more we write, and the sloppier they can get. An edit that pushed a record in where we don't suspect it is a bad edit, even if the user is indeed waiting for that record.
When the test fails, we back off and try again. If the test fails again, we might examine why, and we might find a cleverer and more decoupled way to add that record.
So frequent test runs make sloppy tests _more_ valuable and cost-effective than arbitrarily correct and complex tests.
# I GENERATE THE SEO LINK USING THE ID OF THE LAST INSERT
t = @anuncio.titulo.to_s.downcase.strip.gsub(/[^-_
\s[:alnum:]]/, '').squeeze(' ').tr(' ', '_')
(t.blank?) ? '_' : t
@anuncio.seo = t + '_' + @anuncio.id.to_s
#THEN SAVE AGAIN
@anuncio.save
I dont like this too mutch, 2 saves for the same inserted add, but
thats the way things go.
# I GENERATE THE SEO LINK USING THE ID OF THE LAST INSERT
t = @anuncio.titulo.to_s.downcase.strip.gsub(/[^-_
\s[:alnum:]]/, '').squeeze(' ').tr(' ', '_')
(t.blank?) ? '_' : t
@anuncio.seo = t + '_' + @anuncio.id.to_s
@anuncio.update_attribute :seo, t + ...
Then no save. Do it in one line.
#THEN SAVE AGAIN
@anuncio.save
I dont like this too mutch, 2 saves for the same inserted add, but
thats the way things go.
Can you override the after_create handler? That or a similar handler
might be called after the first time a model record is created, and
when its id field is ready.