How to handle user status in MySQL using sequelize - mysql

I have user's who's status could be active,pending,rejected,de-active,so what is appropriate way to handle status.
I have two scenarios in my mind
1. i can handle it by isPending,isRejected,isActive ,isDe-active flags
2. i can use status flag and can pass 0,1,2,3 corresponding
so my question is what is best way to handle status in MySql, is there any other scenarios
if you know anyone who can help pleas tag them

I believe using a status integer would be a better idea for the following reasons:
Your users can only have one active status at a time, so having only one column enforces that constraint.
In the case where you would like to add another status (for example, expired, if you want to create temporary users), multiple flags would require you to change your schema, as the single column solution would just require you to change your code.
Checking the user status with the first solution requires you to check all these booleans.
Changing the user status with the first solution requires you to update multiple columns as the other solution requires only one column to be updated.

Related

Create or update record for ArchivedUser

I am trying to make a backup table of users, called archived users. It creates the ArchivedUser by taking a hash of the current users attributes (self) and merging in the self.id as the user_id.
When a user is reinstated, their record as an ArchivedUser still remains in the ArchivedUser table. If the user gets deleted a second time, it should update any attributes that have changed.
Currently, it throws a validation error:
Validation failed: User has already been taken, as the self.id already exists in the ArchivedUser table.
What is a better way to handle an object where you update an existing object if possible, or create a new record if it doesn't exist. I am using Rails 4 and have tried find_or_create_by but it throws an error
Mysql2::Error: Unknown column 'device_details.device_app_version'
which is odd, as that column exists in both tables and doesn't get modified.
User Delete Method
# creates ArchivedUser with the exact attributes of the User
# object and merges self.id to fill user_id on ArchivedUser
if ArchivedUser.create!(
self.attributes.merge(user_id: self.id)
)
Thanks for taking a peek!
If your archived_users table is truly acting as a backup for users and not adding any additional functionality, I would ditch the ArchiveUser model and simply add an archived boolean on the User model to tell whether or not the user is archived.
That way you don't have to deal with moving an object to another table and hooking into a delete callback.
However, if your ArchiveUser model does offer some different functionality compared to User, another option would be to use single table inheritence to differentiate the type of user. In this case, you could have User govern all users, and then distinguish between a user being, for example, an ActiveUser or an ArchivedUser.
This takes more setup and can be a bit confusing if you haven't worked with STI, but it can be useful when two similar models need to differ only slightly.
That being said, if you want to keep your current setup, I believe there are a few issues I see with your code:
If you are going to create an object from an existing object, it's good practice to duplicate the object (dup). That way the id won't be automatically set and can be auto-incremented.
If you truly have deleted the User record from the database, there's no reason to store a reference to its id because it's gone. But if you aren't actually deleting the record, you should definitely just use a boolean attribute to determine whether or not the user is active or archived.
I don't have enough context here as to why find_or_create_by isn't working, but if it were the case, then I would keep it as simple as possible. Don't use all the attributes, but just the consistent ones (like id) that you know will return the proper result.
if ArchivedUser.create! # ... is problematic. The bang after create (i.e. create!) will throw an error if the record could not be created, making the if pointless. So, either use if if you don't want errors thrown and want to handle the condition in which the record was not created. Or use create! without if if you do want to throw an error.

Proper way to store requests in Mysql (or any) database

What is the "proper" (most normalized?) way to store requests in the database? For example, a user submits an article. This article must be reviewed and approved before it is posted to the site.
Which is the more proper way:
A) store it in in the Articles table with an "Approved" field which is either a 0, 1, 2 (denied, approved, pending)
OR
B) Have an ArticleRequests table which has the same fields as Articles, and upon approval, move the row data from ArticleRequests to Articles.
Thanks!
Since every article is going to have an approval status, and each time an article is requested you're very likely going to need to know that status - keep it inline with the table.
Do consider calling the field ApprovalStatus, though. You may want to add a related table to contain each of the statuses unless they aren't going to change very often (or ever).
EDIT: Reasons to keep fields in related tables are:
If the related field is not always applicable, or may frequently be null.
If the related field is only needed in rare scenarios and is better described by using a foreign key into a related table of associated attributes.
In your case those above reasons don't apply.
Definitely do 'A'.
If you do B, you'll be creating a new table with the same fields as the other one and that means you're doing something wrong. You're repeating yourself.
I think it's better to store data in main table with specific status. Because it's not necessary to move data between tables if this one is approved and the article will appear on site at the same time. If you don't want to store disapproved articles you should create cron script with will remove unnecessary data or move them to archive table. In this case you will have less loading of your db because you can adjust proper time for removing old articles for example at night.
Regarding problem using approval status in each query: If you are planning to have very popular site with high-load for searching or making list of article you will use standalone server like sphinx or solr(mysql is not good solution for this purposes) and you will put data to these ones with status='Approved'. Using delta indexing helps you to keep your data up-to-date.

Table for checklist MYSQL

I am trying to set up a few checklists, which users can save & go back to. I haven't set up user profiles yet.
How should I set up MySQL database? So far I have one database (e.g. lists_db), and am creating a new table for each separate list. Is this the right way to do it?
Also, what fields shall I have? ID presumably, and then what? How does MySQL read checkboxes?
Thanks in advance :-)
Are you storing the questions and answers or just the answers? If you just had one list, you could create a table for the questions (columns question_id, question_text) and a table for the answers (columns question_id, user_id, checked).
You could create a new table for every list, but this might be cumbersome. With two separate tables, it's possible to add a column to the questions (question_group_id) and store everything in a single column.
Regarding how MySQL reads checkboxes, databases generally don't store information specific to a UI component. In this case, the underlying data element is a boolean indicating whether it is checked or not - or in MySQL, a bit datatype.
I suspect you may be conflating persistence with user interface. MySQL has no notion of a 'check box'. Rather, a database is a representer of facts: It will remember the information you ask it to remember, but it makes no attempt at organizing that information in a way that's useful to a particular application.
As for remembering whether a box has been checked, you most likely want BOOLEAN (a synonym for TINYINT(1). You would represent an unchecked box with a value of zero, and a checked box with a non-zero value.

What's the best way to save trivial user states (e.g. dismissed welcome msg) in database?

Should I use (create) a column for every new state? Or one field with a bunch of comma separated states (alternatively a json obj)? Any suggestions welcome.
UPDATE
First let me day thanks for the answers. I just want to clear up, what options I see:
Put a column for every state in the user row (initial plan) / Can get messy with lots of states (in the future)
Put one column with json/xml data in the user row / Easy to maintain (no db change required), but doesn't feel right
Have a dedicated states table (thx lhiles)/ Sounds cool, how would this table look like?
I'm looking for pros/cons of the different implementations. Again: Thanks!
Create a column for each state. This is proper data normalization.
With a column for each state you can retrieve as few or as many states as needed for the current operation.
All of the states returned will be contained in a single row with each column named. This makes referencing each state value very easy.
It allows you to easily add constraints to each state as needed. (State X can only contain '1' or '2'.)
It allows you to easily query states across users. (How many users have set a state value to 'X'?)
My preferred method is to create a dedicated table for user settings. Each state/setting corresponds to a column within that table. As your project grows additional columns can be added without cluttering your apps core data.
Another route, if you feel that there will be too many settings to devote 1 setting per column, would be to store the settings as XML (or json as you mentioned) data within SQL. This would allow you to derive any type of state format you wanted, however, it puts more work on the programmer to parse, validate, and persist those settings.
You can save state using an ENUM if the states are mutually exclusive; e.g. person is male or female.
Or using a SET if states can co-exist; e.g. person is a member of (AA and CA and SOsA*)
A sample table using both:
CREATE TABLE test.table1(
test_enum ENUM('male', 'female') DEFAULT 'male',
test_set SET('AA', 'CA', 'SOsA') DEFAULT NULL
)
ENGINE = INNODB;
If you're using an ENUM I personally would recommend you set an explicit default value other than null, because most of the time a choice must be made.
Link: http://dev.mysql.com/doc/refman/5.1/en/constraint-enum.html
* (stackoverflow sufferers anonymous)
I really wouldn't do this with a column per setting, as most of the other people are suggesting. I'd do a setting per row because this doesn't require schema changes (including upgrade scripts) every time you add a setting.
Better yet, write some reflection code to run on app startup that'll look at the entries on an enum and automatically create a record in the database (with some default value that you specify in a custom attribute on each enum value).
I recently did something like I'm indicating above. Now to add a new setting, I add an entry to an enum and that's it. New settings take about 10 seconds.
I may put my code up on CodeProject, it has has made development easy.

get the next id

My question is how to get the next id using NHibernate in a mysql db for an auto-increment ID column ?
Thanks,
Based on the further description you give (as an answer?) below it seems to me that you are indeed looking for the NHibernate feature to automatically read back IDs generated by the database: identity
This will tell NHibernate the ID's value is determined by the database upon insert, it will not send a value as part of its INSERT statement and it will read back the value of the ID column after it has performed the insert. But you do have to tell the database (in the table definition) that it should auto-generate a value for the ID column for each record inserted...
You're going to create a race condition if you do this. To answer your question, I don't think there is a specific way for Hibernate to give you this information since no application can give you this information. By getting the "next id", by the time it returns that data to you, it might be invalid already. The easiest way I can think of is to get the last_insert_id() and add +1 to it.
Why don't you post more information about you're trying to accomplish and we can find a better solution for you?
Provided that you are the only writer to your database then you could get your application to maintain the sequence number for you and allocate the next number yourself.
If you want to do this then you'll want to ensure that your application counter is thread safe.
You'll also want a way to get the last written sequence number when restarting you application.