The ruby on rails can't manually delete records? - ruby-on-rails

I have a database the have orders, and which order many order items, that kinds of thing. I deleted one product carelessly, and it is related to the order items, so it can't load successfully. So, I use the SQLite Database Browser to delete the orders and order items. But after I restart the server, it prompt me that :
We're sorry, but something went wrong.
We've been notified about this issue
and we'll take a look at it shortly.
Notice that I am using the development mode.

Did you save the database and close the SQLite browser? Your database may be locked.
You may also have forgotten to delete certain orders, so it's looking for a product that doesn't exist.
In the future, make sure you're in development mode, since that tends to offer more descriptive error messages.

This is a standard Rails error message.
You should look the development log to figure out what exactly is happening.
You can manually modify your record as soon as your changes don't break data integrity.
It's recommended you use ActiveRecord :dependent association option to specify what ActiveRecord should to when a record of that specific class is destroyed.
Also note that record.delete is different than record.destroy. The first one doesn't execute associated callbacks.

Related

Admin user approving SQL changes from a user

I've read into Cancan and Pundit (also Devise) for managing users in a Rails App. But I wanted to know if something was possible.
Basically, I want to have users change/add lines in a table (using SQLite at the moment, but will be moving to SQL in the future - call them entries). But before it gets added to the actual table, it gets sent to the admin for approval. Then the admin can just hit 'approve' and the statement gets run.
I'm just confused about how to hold the statement and then when approved, the statement runs. Any information would be appreciated.
By statement, do you mean that your users are actually writing the SQL themselves?
If not, I'd setup a second model identical to your first that acts like a queue of some sort that holds the proposed changes/additions. This way, you'll be able to compare the old and new statements if necessary, and, when approved, you'll be able to perform the create/update magic on your original model.
Hope this gives you some ideas!

Heroku PG Backups, how to restore certain records only

I would like to use Heroku PG Backups to able to restore my data in case anything was deleted by mistake. My question is, what if I want to restore just a certain record as well as its associations. Like a student and his grades for example..
I found a similar question: How do I restore three items from a backup made using Heroku PG Backups?
However, I don't know what it means to cherry pick items.. How do I do that? .. manually?
Thank you,
However, I don't know what it means to cherry pick items.. How do I do that? .. manually?
It's a manual process, yes. You can for example use dblink[0] to connect from one DB to the other and pull in the relevant records.
[0] http://www.postgresql.org/docs/9.1/static/dblink.html
Here's a full example on how to use dblink on heroku:
https://gist.github.com/hgmnz/5100682

is there anyway to undo an activerecord delete in rails console?

I have made an unbelievably horrible mistake in script/console:
user.delete
Is there any way to undo that from within the same script/console session?
Well, if you remain to have access to the deleted record, you can just create a new replica like this
User.new(user.attributes_hash).save
That will just create a user with the exaxt same attributes (yes, also the id) and save it to the DB. I use this to undo a destroy action using the flash.
Caveat. If you have used the User#destroy method and your model has relations with dependent: :destroy or dependent: :delete, then those dependent records – if present when executing the command – will be lost. Unless, of course, you have active references, i.e. variables, to the deleted/destroyed records.
I don't know of a way either, it might be possible that you still have the information in your shell history. (Just scroll up till you executed user.delete). You could manually restore the user instance, which gets tricky if you had dependencies/associations.
For the future: you might want to start the console in sandbox mode via:
rails console -s
All changes will be rolled back after you close it.
Edit: Please take a look at Arne L.'s Answer it shows a way to save the user to the database if the object is still available. Thats much better than what I proposed ("manually restore the user").
Unfortunately, no. Unless you're using a gem like Papertrail that's keeping a history of your changes, the record is gone.

Allow users to remove their account

I am developing a gallery which allows users to post photos, comments, vote and do many other tasks.
Now I think that it is correct to allow users to unsubscribe and remove all their data if they want to. However it is difficult to allow such a thing because you run the risk to break your application (e.g. what should I do when a comment has many replies? what should I do with pages that have many revisions by different users?).
Photos can be easily removed, but for other data (i.e. comments, revisions...) I thought that there are three possibilities:
assign it to the admin
assign it to a user called "removed-user"
mantain the current associations (i.e. the user ID) and only rename user's data (e.g. assign a new username such as "removed-user-24" and a non-existent e-mail such as "noreply-removed-user-24#mysite.com"
What are the best practices to follow when we allow users to remove their accounts? How do you implement them (particularly in Rails)?
I've typically solved this type of problem by having an active flag on user, and simply setting active to false when the user is deleted. That way I maintain referential integrity throughout the system even if a user is "deleted". In the business layer I always validate a user is active before allowing them to perform operations. I also filter inactive users when retrieving data.
The usual thing to do is instead of deleting them from a database, add a boolean flag field and have it be true for valid users and false for invalid users. You will have to add code to filter on the flag. You should also remove all relevant data from the user that you can. The primary purpose of this flag is to keep the links intact. It is a variant of the renaming the user's data, but the flag will be easier to check.
Ideally in a system you would not want to "hard delete" data. The best way I know of and that we have implemented in past is "soft delete". Maintain a status column in all your data tables which ideally refers to the fact whether the row is active or not. Any row when created is "Active" by default; however as entries are deleted; they are made inactive.
All select queries which display data on screen filter results for only "active records". This way you get following advantages:
1. Data Recovery is possible.
2. You can have a scheduled task on database level, which can take care of hard deletes of once in a way; if really needed. (Like a SQL procedure or something)
3. You can have an admin screen to be able to decide which accounts, entries etc you'd really want to mark for deletion
4. A temperory disabling of account can also be implemented with same solution.
In prod environments where I have worked on, a hard delete is a strict No-No. Infact audits are maintained for deletes also. But if application is really small; it'd be upto user.
I would still suggest a "virtual delete" or a "soft delete" with periodic cleanup on db level; which will be faster efficient and optimized way of cleaning up.
I generally don't like to delete anything and instead opt to mark records as deleted/unpublished using states (with AASM i.e. acts as state machine).
I prefer states and events to just using flags as you can use events to update attributes and send emails etc. in one foul swoop. Then check states to decide what to do later on.
HTH.
I would recommend putting in a delete date field that contains the date/time the user unsubscribed - not only to the user record, but to all information related to that user. The app should check the field prior to displaying anything. You can then run a hard delete for all records 30 days (your choice of time) after the delete date. This will allow the information not to be shown (you will probably need to update the app in a few places), time to allow the user to re-subscribe (accidental or rethinking) and a scheduled process to delete old data. I would remove ALL information about the member and any related comments about the member or their prior published data (photos, etc.)
I am sure it changing lot since update with Data Protection and GDPR, etc.
the reason I found this page as I was looking for advice because of new Apply policy on account deletion requirements extended https://developer.apple.com/news/?id=i71db0mv
We are using Ruby on Rails right now. Your answers seem a little outdated? or not or still useful right now
I was thinking something like that
create a new table “old_user_table” with old user_id , First name, Second name, email, and booking slug.
It will allow keep all users who did previous booking. And deleted their user ID in the app. We need to keep all records for booking for audit purpose in the last 5 years in the app.
the user setup with this app, the user but never booking, then the user will not transfer to “old_user_table” cos the user never booking.
Does it make sense? something like that?

Techniques for storing/retrieving historical data in Rails

I'm looking for some ideas about saving a snapshot of some (different) records at the time of an event, for example user getting a document from my application, so that this document can be regenerated later. What strategies do you reccomend? Should I use the same table as the table with current values or use a historical table? Do you know of any plugins that could help me with the task? Please share your thoughts and solutions.
There are several plugins for this.
Acts_audited
acts as audited creates a single table for all of the auditable objects and requires no changes to your existing tables. You get on entry per change with the changes stored as a hash in a memo field, the type of change (CRUD). It is very easy to setup with just a single statement in the application controller specifying which models you want audited.
Rolling back is up to you but the information is there. Because the information stored is just the changes building the whole object may be difficult due to subsequent changes.
Acts_as_versioned
A bit more complicated to setup- you need a separate table for each object you want to version and you have to add a version id to your existing table. Rollback is a very easy. There are forks on github that provide a hash of changes since last version so you can easily highlight the differences (it's what I use). My guess is that this is the most popular solution.
Ones I have no experience with: acts_as_revisable. I'll probably give this one a go next time I need versioning as it looks much more sophisticated.
I did this once awhile back. We created a new table that had a very similar structure to the table we wanted to log and whenever we needed to log something, we did something similar to this:
attr = object_to_log.attributes
# Remove things like created_at, updated_at, other unneeded columns
log = MyLogger.new(attrs)
log.save
There's a very good chance there are plugins/gems to do stuff like this, though.
I have used acts_as_versioned for stuff like this.
The OP is a year old but thought I'd add vestal_versions to the mix. It uses a single table to track serialized hashes of each version. By traversing the record of changes, the models can be reverted to any point in time.
Seems to be the community favorite as of this post...

Resources