Scaffolding user ID resetting - ruby-on-rails

in the application i am currently creating in ruby on rails. I am trying to do some tests in rails console where i have to destroy data in the database and the database is connected to a server. I am importing an XML and parsing it and putting it into a database with scaffolding.
Now what i need: Basically what i am attempting to do is to destroy the data and replace it with a new one every week..but the problem i am getting, the userid is gone up to 700+ and there are only 50 records :S cause it doesnt reset...
To delete all records i am currently using "whatever.destroy_all" does the trick
Any help?
Btw i am using SQLITE

The ID column created in the table usually is set as unique and to increment by 1 for each new record, which is why each time you destroy and add new data the ID keeps getting higher.
The fact that the ID # is getting larger and larger is not an issue at all.
If you really want to start back at zero, I would think you could drop the table and recreate it, but that seems like overkill for a trivial issue.
Regarding the connection to the other scaffold, how are you connecting the two and what do they both represent?

Ideally the data population for testing should be done through fixtures (or easy tools such as factorygirl etc..)
The main advantage of having a fix data set is you can run your tests in any environment. But as per your requirement you can do something like this,
When you populate the date through the active records pass the id parameter as well
Ex: User.new(:id => 1, :name => "sameera").create
By this way you can have constant id's But make sure you increment the id accordingly.

Related

What causes postgresql sequence to fall out of sync with table id in rails app?

I recently had the very unpleasant experience of the postgresql sequence falling out of sync with the table id in a rails app. Until this happened, rails 'magic' meant that I had never known what a postgresql sequence was - it had always happened automagically. Even more alarmingly, I didn't even know when I had caused this 'out of sync' issue to occur (it was only when later records were created that the errors were thrown)
I managed to wade my way through the drama. But now I want to understand all the possible causes of such a severe problem as the postgresql sequence falling out of sync with the id in a rails table. I want to know this so I can avoid it in the future.
I caused it to happen by creating new records manually where I specified the id. E.g. User.create(id: 4566, name: "Jo", email: "jo#gmail.com") (importantly, creating the record without specifying the id would have avoided the issue i.e. User.create(name: "Jo", email: "jo#gmail.com")
My question: in addition to specifying ids in newly created records, what other things does a rails dev need to know will cause this issue?
A pg sequence does not follow transaction semantics, it just returns its older value +1 every time it's asked to. If you open a transaction, create some records, but then rollback, the records you created will not be persisted in the DB but the sequence will still be incremented the next time it's used.
It cannot follow transaction semantics because it's supposed to keep track of a "global state counter". If two concurrent transactions were to create a new row in the same table, we want both to have different ids, for example.
My advice would be to not explicitly set id's on the DB. If you need a custom identifier, use another column.

Rails - dumping the database into a file

What I want to do is to dump the database into a custom created .rb file.
I found a seed_dump gem that allows me to do this:
rails db:seed:dump FILE=db/seeds/my_db_file_name.rb
Then I noticed that my datebase is our of order, so I found this on SO to include the ids:
rails db:seed:dump FILE=db/seeds/my_db_file_name.rb EXCLUDE=[]
Seemed fine until I wanted to add new record to my database. Turned out that reseting primary keys solved the problem:
def reset_pk
ActiveRecord::Base.connection.tables.each do |t|
ActiveRecord::Base.connection.reset_pk_sequence!(t)
end
redirect_to root_url
end
What I am now want to do is to simplify the dumping process, as for now, every time I dump the data base the records are "out of order", what I will explain below.
Let's assume I have a two models: Lab and Offer. Lab can have many offers. So in order to create an Offer object I first have to create a Lab object. But when I dump the schema my file looks like this:
Offer.create...
Offer.create...
Offer.create
Lab.create...
Lab.create...
Lab.create...
and if I try to seed it, it won't do it as Offers are created before Labs, and it should be the other way.
My question is, is there a way to actually keep the relationships while dumping the database so Labs get created first?
EDIT
I managed to do something like this:
rails db:seed:dump FILE=db/seeds/my_db_file_name.rb EXCLUDE=[] MODELS="Lab, Offer"
This one keeps the order as I want it, but I wonder if there is a simple way (in case of having 15, 20 models instead of just 2).
You could try dumping/restoring one table at a time in the order you wish.

ROR maintain history of object updates

I have a model which I want to store a history of changes to, my plan is to rather than update an object create a new one and on a show only fetch the latest version.
This plan presents a number of difficulties firstly the id will be different after a update I indend to get around this by keeping a second ID column which will be the same for all updates of that instance.
to that end I have created a SQLite sequence for this second coloumn.
my question is how can I get values from this sequence in the model/controller as I will only want to get from it on first time the object is created, secondly how can I use this second ID column as the URL for the object so it is fixed throughout updates.
Many Thanks,
Check out the PaperTrail gem. It might do what you want and sidestep those issues completely.
https://github.com/airblade/paper_trail

Rails reset single column

I am trying to implement a rake task that will run once a month to reset a single column. I would prefer to reset the column to its default value but I cannot find any methods to help me accomplish this. reset_column_information does not work
What is the most efficient way to reset a single column in active record?
Base method #update_all does the update direct in the database, so it is very efficient. However it bypasses callbacks because the models aren't loaded: http://apidock.com/rails/ActiveRecord/Base/update_all/class
SomeModel.update_all("some_column = 4"); # sets all some_column attributes to 4
Resetting it to the default depends on how you are setting the default in the first place. If the default is calculated in the model, then you would have to select and instantiate all the records, which could be very slow. If it's defined in the database, maybe it would be possible but I think it would be database specific.
If you're hardcore you can also drop the column(s) in a migration and then recreate it/them. Sometimes this will be a lot faster. I wouldn't do it in a critical application automatically - but if you're fiddling with your own local machine and just want to test stuff quick, this can be effective.

Modifying Database IDs from Rails Console?

I have a small database and have been adding entries through a Rails page. I "destroyed" one of the entries and now my sequence of IDs are skipping by one. For example, I now have 42 then 44, instead of the obvious: 42, 43, 44.
I was wondering if there was a way to edit the ID number of a new object through the console. I have tried:
record.id = 43
record.save
and
record = record.new
record.attributes = { :id => 43 }
but both didn't work. I'm fairly certain there has to be a console method for this, but I can't seem to find much specific on Google and I probably read the Rails API incorrectly... Would I possibly have to do this through direct SQL in sqlite?
Thanks
The best way to do it is to execute the SQL directly, and solve this temporal glitch in the sequence.
Try accessing the console (ruby script/console) and type:
>> sql = "update records set id=43 where id=44"
>> ActiveRecord::Base.connection.execute(sql)
Where 44 is the newly created object's id, and 43 is the one you were missing in your table
Good luck!
Actually, you can set the id manually for new objects:
record = Record.new
record.id = 1234
record.save
However, what you're trying to do is update the id of an existing object. When you set record.id = 43 and then call save what happens is that ActiveRecord will try to generate SQL like this:
update records set id = 43 where id = 43
Notice that the id it's looking for to update is the same as the one you're trying to change. That's why it doesn't work.
So yes, you would have to use SQL to change this. Whether or not that's a good idea is another issue, but sometimes it needs to be done.
Would I possibly have to do this through direct SQL in sqlite?
Yes.
The whole point of ActiveRecord is that is abstracts DB functions and just returns collections of data. You shouldn't be worrying about the ID of a record, that is something specific to the DB. Off the top of my head I can't think of any reasons to reference the model's ID.
If your app depends on having a sequenced number then you should add another field to the model which has this. For instance, if I have a store with products (a Product model) and I give the ID number the DB provides to other vendors. Two weeks later, my boss asks me to have a unique, but similar ID for two variations of products: "45a" and "45b". Nuts. The ID field should only be used by to the database and ActiveRecord, not you or your users, to identify the record.
There is a small chance that there might be an obscure method which force sets the ID if the DB allows it, but it is obscure for a reason. Don't try and find it :)
All that being said, type ruby script/dbconsole to quickly pull up the sqlite interface without having to type your password.
Also, if you delete the sqlite database that will reset the counter and start at 0. With great power comes great responsibility.
EDIT
If I remember correctly Dave Thomas wrote about this somewhere. Perhaps here?

Resources