I am creating a web application using Strongloop using a MySQL database connector.
I want it to be possible, that a user can modify data in the application - but that this data will not be 'saved' until a user expressly chooses to save the data.
On the other hand, this is a web application and I don't want to keep the data in the user's session or local storage - I want this data to be immediately persisted so it can be recovered easily if the user loses their session.
To implement it I am thinking of doing the following, but I'm not sure if this is a good idea, or if there is a better way to be doing this.
This is one was I can implement it without doing too much customization on an existing relation:
add an new generated index as the primary key for the table
add a new generated index that represents the item in the row
this would be generated for new items, or set to an old item for edits
add a boolean attribute 'saved'
Data will be written as 'saved=false'. To 'save' the data, the row is marked saved and the old row is deleted. The old row can be looked up by it's key, the second attribute in the row.
The way I was thinking of implementing it is to create a base entity called Saveable. Then every Database entity that extends Saveable will also have the 'Saveable' property.
Saveable has:
A generated id number
A generated non id number - the key for the real object
A 'saved' attribute
I would then put a method in Savable.js to perform the save operation and expose it via the API, and a method to intercept new writes and store them as unsaved.
My question is - is this a reasonable way to achieve what I want?
Related
I have an Access application, which is under development, some test data has already been created and should change to actual operation.
There are many tables which have a relationship, connecting each table by id number. I want to reset the ID number from 1 continuously.
I researched some method, all the methods are below,
Data deleting, initializing and adding.
Above method used, maybe all data was reset and I must input them again.
Is it possible to restructure data and relationship remains unchanged?
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.
Say my Couchbase DB has millions of user objects, each user object contains some primitive fields (score, balance etc.)
And say I read & write most of those fields on every server request.
I see 2 options of storing the User object in Couchbase:
A single JSON object mapped to a user key (e.g. user_555)
Mapping each field into a separate entry (e.g. score_555 and balance_555)
Option 1 - Single CB lookup, JSON parsing
Option 2 - Twice the lookups, less parsing if any
How can I tell which one is better in terms of performance?
What if I had 3 fields? what if 4? does it make a difference?
Thanks
Eyal
Think about your data structure and access patterns first before worrying if json parsing or extra lookups will add overhead to your system.
From my perspective and experience I would try to model documents based upon logical object groupings, I would store 'user' attributes together. If you were to store each field separately you'd have to do a series of lookups if you ever wanted to provide a client or service with a full overview of the player profile.
I've used Couchbase as the main data store for a social mobile game, we store 90% of user data in a user document, this contains all the relevant fields such as score,level,progress etc. For the majority of operations such as a new score or upgrades we want to be dealing with the whole User object in the application layer so it makes sense to inflate the user object from the cb document, alter/read what we need and then persist it again if there have been changes.
The only time we have id references to other documents is in the form of player purchases where we have an array of ids that each reference a separate purchase. We do this as we wanted to have richer information on each purchase (date of transaction,transaction id,product type etc) that isn't relevant to the user document as when a purchase is made we verify it's legitimate and then add to the User inventory and create the separate purchase document.
So our structure is:
UserDoc:
-Fields specific to a User (score,level,progress,friends,inventory)
-Arrays of IDS pointing to specific purchases
The only time I'd consider splitting out some specific fields as you outlined above would be if your user document got seriously large but I think it'd be best to divide documents up per groupings of data as opposed to specific fields.
Hope that helped!
I am almost done researching for my application. The last thing that I need to be able to learn how to do is the following situation: Let's say I have created a UItableview drilldown app, but once the user gets to the end of that drill down (their choices on a specific dog product for instance are now very specific), they can save that information. What I want my app to do here is, at the end of the drilldown, save their entire nsindexpath as another entity so that I can send this information later up to my MySQL database. My question is, how could I re-save an nsstring from an nsindexpath in another entity?
Start writing code instead of researching your entire app's architecture before you start it. You really only will learn from actually programming.
Use Core Data
Use tableView:didSelectRowAtIndexPath: to obtain the selected tableview cell's indexPath and store the indexPath or the data as needed.
I agree with runmads suggestions. CoreData will probably make your life easier in the long run. To answer your question though:
Don't save the table view's NSIndexPath. The selection index path is a view related property (in MVC terms). Your users choice belongs to the model domain. It's bad practice to mix the two and if you later insert new choices in one of your tables, your stored index paths will become invalid.
Instead create something like a UserChoice object or a dictionary or an array which you can pass down your tableview controllers as the user drills down. When the user selects a cell, add the primary key of the associated data object to your array. At the end, store the primary keys you've collected along the way into your database.
Let's say I have a database that stores Fruit and FruitBaskets, and it's already populated with plenty of each. In my code I'm using Linq-to-Sql so that I can treat the rows of the database as instances of the OO classes Fruit and FruitBasket. Let's say that I want to create a temporary FruitBasket in code, process with it, but I do not want the FruitBasket to be persisted to the database. How do I achieve this using Linq-to-Sql?
The default I've found in Linq-to-Sql is that if I create a new, empty FruitBasket and add a Fruit to it that I had retrieved from the database, then the new FruitBasket will be automatically inserted to the data base upon my call to dataContext.SubmitChanges() (whether or not I have called insertUponSubmit()). Usually this is the right thing , but sometimes I want to be able to create a new FruitBasket without having it automatically inserted into the DB. Ideas? Best practices?
If you set DataContext.ObjectTrackingEnabled = false; then it shout prevent this. You need to make sure you set it before querying the data context.