I would like to provide users with points when they do a certain thing. For example:
adding article
adding question
answering question
liking article
etc.
Some of them can have conditions like there are only points for first 3 articles a day, but I think I will handle this directly in my code base.
The problem is what would be a good database design to handle this? I think of 3 tables.
user_activities - in this table I will store event types (I use
laravel so it would probably be the event class name) and points for
specific event.
activity_user - pivot table between user_activities and users.
and of course users table
It is very simple so I am worrying that there are some conditions I haven't thought of, and it would come and bite me in the future.
I think you'll need a forth table that is simply "activities" that is simply a list of the kinds of activities to track. This will have an ID column, and then in your user_activities table include an 'activity_id' to link to that. You'll no doubt have unique information for each kind, for example an activities table may have columns like
ID : unique ID per laravel
ACTIVITY_CODE : short code to use as part of application/business logic
ACTIVITY_NAME : longer name that is for display name like "answered a question"
EVENT : what does the user have to do to trigger the activity award
POINT_VALUE: how many points for this event
etc
If you think that points may change in the future (eg. to encourage certain user activities) then you'll want to track the actual point awarded at the time in the user activities table, or some way to track what the points were at any one time.
While I'm suggesting fourth table, what you really need is more carefully worded list of features to be implemented before doing any design work. My example of allowing for points awarded to change over time is such a feature that you don't mention but you'll need to design for if this feature is needed.
Well I have found this https://laracasts.com/lessons/build-an-activity-feed-in-laravel as very good solution. Hope it helps someone :)
We are working on implementing the FHIR API in a veterinary health care system. One question that has come up is which resource type we should be using for the owner of the animal (patient). In the context of the animal it is easy to see that the owner information can go into the contact of the Patient resource.
However, an animal owner is quite often referenced outside the context of an individual patient. So that leads me to RelatedPerson. The description of the RelatedPerson resource gives an example of "The owner or trainer of a horse", so it seems it might fit. However, one big issue with this is that a RelatedPerson can only be linked to a single patient. The relationship between animals and owners in the veterinary domain is many to many. So an owner often has more than one animal.
This issue led me to the Person resource. This at least gives a way to have multiple Patient's (animals) belonging to one Person (owner).
In either case we'll have to add a "percentOwnership" attribute as an extension to the resource since an animal can potentially have multiple owners.
If this is the way we should do it (using the Person resource), my next question is how would one search using the API for all Patient's linked from a given Person? If we used the RelatedPerson (which is probably not workable due to the limitation mentioned above), it seems like this search would use the relatedPerson compartment to search. However, there doesn't seem to be a person compartment in the spec.
Summary:
What resource to use for the owner of an animal?
How to search for all animals belonging to a particular owner?
If you just want contact information, then Patient.contact is fine. If you're interested in the owner as a potential actor (information recipient, informer, performer, etc.) then RelatedPerson will be necessary. However, RelatedPerson is specific to a particular Patient's record (i.e. you'll have a distinct RelatedPerson instance for each animal). To link all of the RelatedPerson instances together and say "this is the same person", you'd use Person. To query, you'd query on Person where link matched one of the desired RelatedPerson records. Then you'd need to do an include of Person.link and RelatedPerson.patient to bring back all of the animals
I just ran into an interesting situation about relationships and databases. I am writing a ruby app and for my database I am using postgresql. I have a parent object "user" and a related object "thingies" where a user can have one or more thingies. What would be the advantage of using a separate table vs just embedding data within a field in the parent table?
Example from ActiveRecord:
using a related table:
def change
create_table :users do |i|
i.text :name
end
create_table :thingies do |i|
i.integer :thingie
i.text :discription
end
end
class User < ActiveRecord::Base
has_many :thingies
end
class Thingie < ActiveRecord::Base
belongs_to :user
end
using an embedded data structure (multidimensional array) method:
def change
create_table :users do |i|
i.text :name
i.text :thingies, array: true # example contents: [[thingie,discription],[thingie,discription]]
end
end
class User < ActiveRecord::Base
end
Relevant Information
I am using heroku and heroku-posgres as my database. I am using their free option, which limits me to 10,000 rows. This seems to make me want to use the multidimensional array way, but I don't really know.
Embedding a data structure in a field can work for simple cases but it prevents you from taking advantage of relational databases. Relational databases are designed to find, update, delete and protect your data. With an embedded field containing its own wad-o-data (array, JSON, xml etc), you wind up writing all the code to do this yourself.
There are cases where the embedded field might be more suitable, but for this question as an example I will use a case that highlights the advantages of a related table approch.
Imagine a User and Post example for a blog.
For an embedded post solution, you would have a table something like this (psuedocode - these are probably not valid ddl):
create table Users {
id int auto_increment,
name varchar(200)
post text[][],
}
With related tables, you would do something like
create table Users {
id int auto_increment,
name varchar(200)
}
create table Posts {
id auto_increment,
user_id int,
content text
}
Object Relational Mapping (ORM) tools: With the embedded post, you will be writing the code manually to add posts to a user, navigate through existing posts, validate them, delete them etc. With the separate table design, you can leverage the ActiveRecord (or whatever object relational system you are using) tools for this which should keep your code much simpler.
Flexibility: Imagine you want to add a date field to the post. You can do it with an embedded field, but you will have to write code to parse your array, validate the fields, update the existing embedded posts etc. With the separate table, this is much simpler. In addition, lets say you want to add an Editor to your system who approves all the posts. With the relational example this is easy. As an example to find all posts edited by 'Bob' with ActiveRecord, you would just need:
Editor.where(name: 'Bob').posts
For the embedded side, you would have to write code to walk through every user in the database, parse every one of their posts and look for 'Bob' in the editor field.
Performance: Imagine that you have 10,000 users with an average of 100 posts each. Now you want to find all posts done on a certain date. With the embedded field, you must loop through every record, parse the entire array of all posts, extract the dates and check agains the one you want. This will chew up both cpu and disk i/0. For the database, you can easily index the date field and pull out the exact records you need without parsing every post from every user.
Standards: Using a vendor specific data structure means that moving your application to another database could be a pain. Postgres appears to have a rich set of data types, but they are not the same as MySQL, Oracle, SQL Server etc. If you stick with standard data types, you will have a much easier time swapping backends.
These are the main issues I see off the top. I have made this mistake and paid the price for it, so unless there is a super-compelling reason do do otherwise, I would use the separate table.
what if users John and Ann have the same thingies? the records will be duplicated and if you decide to change the name of thingie you will have to change two or more records. If thingie is stored in the separate table you have to change only one record. FYI https://en.wikipedia.org/wiki/Database_normalization
Benefits of one to many:
Easier ORM (Object Relational Mapping) integration. You can use it either way, but you have to define your tables with native sql. Having distinct tables is easier and you can make use of auto-generated mappings.
Your space limitation of 10,000 rows will go further with the one to many relationship in the case that 2 or more people can have the same "thingies."
Handle users and thingies separately. In some cases, you might only care about people or thingies, not their relationship with each other. Some examples, updating a username or thingy description, getting a list of all thingies (or all users). Selecting from the single table can make it harding to work with.
Maintenance and manipulation is easier. In the case that a user or a thingy is updated (name change, email address update, etc), you only need to update 1 record in their table instead of writing update statements "where user_id=?".
Enforceable database constraints. What if a thingy is not owned by anyone? Is the user column now nillable? It would have to be in the single table case, so you could not enforce a simple "not nillable" username, for example.
There are a lot of reasons of course. If you are using a relational database, you should make use of the one to many by separating your objects (users and thingies) as separate tables. Considering your limitation on number of records and that the size of your dataset is small (under 10,000), you shouldn't feel the down side of normalized data.
The short truth is that there are benefits of both. You could, for example, get faster read times from the single table approach because you don't need complicated joins.
Here is a good reference with the pros/cons of both (normalized is the multiple table approach and denormalized is the single table approach).
http://www.ovaistariq.net/199/databases-normalization-or-denormalization-which-is-the-better-technique/
Besides the benefits other mentioned, there is also one thing about standards. If you are working on this app alone, then that's not a problem, but if someone else would want to change something, then the nightmare starts.
It may take this guy a lot of time to understand how it works alone. And modifing something like this will take even more time. This way, some simple improvement may be really time consuming. And at some point, you will be working with other people. So always code like the guy who works with your code at the end is the brutal psychopath who knows where you live.
I am building a feature where when a person signs up for an account we will automatically populate their account with default categories and items to get them started.
Further, they can optionally purchase additional category sets to add/populate their accounts at anytime.
I am thinking my choices are:
1) Somehow use seeds.rb
2) Store these records in a YAML file and load in upon account creation
3) Store these records in the DB as a default set and clone/dup them.
Any help appreciated w/ code examples to get me started.
This is what I would do:
Have a flag in the DB to identify first_sign_in Store the data in a yaml file (e.g db/users.yml) and do:
def populate_user
user.update_attributes(YAML.load(Rails.root + 'db/users.yml')) if first_sign_in == 0
end
Then you can add this to an after_create hook so it is called only when a user is created
I'd do it differently. I'd have a "Registration" form object between the controller and model(s). Have this build some default categories and items at the same time as it first builds a user. How you isolate the attributes of those default items depends on how complex they are. If they're simple a default hash in the form object will suffice, if they're complex you can pull in from YML.
When I've done this in the past - had a signup which requires multiple object creation I've had a RegistrationsController, a RegistrationForm object which takes the params and validates everything, and is also responsible for knowing what to save, and sometimes in intermediate Registrar object (Struct usually) which has all the logic for callbacks. The registrations_controller initializes a registrar which is sent a message register(registration_form).
This leads to isolation of responsibilities and much cleaner code in the long run.
The answers provided are definite options, with which I experimented with. However, I decided to go a different route. I realized that I would need to manage these 'template' records and a DB would be easiest.
1) I setup a column on the table 'is_template' to mark the records that will be used to seed other accounts.
2) Created an after_create call back to seed the accounts using these records.
3) To make matters easier I used the amoeba gem which allows me to copy the records and their associated records which works great since some of them have has_many relationships.
This has been working great so far - and I also have a way for myself and the non-tech staff to update the records.
So I'm building out a web app using rails and devise for authentication, and I've run into a conceptual question concerning the setup of my database.
The idea of the site is that there are two different types of users, each has its own permissions and views. For instance, when somebody registers they choose to have either user type 1 or user type 2. Then after sign up, depending on their choice, they are presented with different forms to fill in their profile, etc. The permissions come into play because type 1 users can see type 2 users but can't see other type 1 users' profiles, while type 2 users can see everyone's profiles.
Now the way I set it up, I have two separate models; one for each type of user. However, after browsing a bunch online, I've read that a lot of people only use one model, namely User, with a user-type column that identifies their type to load the appropriate resources. Before I get too far along in my approach, I'm just wondering what are the pros and cons of having multiple models for user types?
I suggest you use Single Table Inheritance:
class User < ActiveRecord::Base
# Data shared by all kinds of users
end
class Type1User < User
# Data specific to type 1 user
end
class Type2User < User
# Data specific to type 2 user
end
All these models will be saved on the users table, but will have a type column which allows you to tell them apart. Users returned by find and company will also be instances of the appropriate class.
Related:
Single Table Inheritance And where to use it in Rails
Martin Fowler on Single Table Inheritance