Saving player statistics (different for each game) to database in Rails - ruby-on-rails

I probably could not find anything about this because I don't know how to describe it.
I have the following setup:
A user account can have a profile with basic information (name, age), optional and there can also be a profile without associated account.
A profile can be linked to several gameprofiles (one for each game)
A gameprofile has an ingame name and should be where I can find a player's statistics.
Now, for different games, there are different statistics. Do I really need to create another model for each game with the associated attributes or is there a smarter way to do this?

#Okomikeruko makes a good point about different game stats described by different attributes. You should be warned though that hash in string approach will complicate querying and indexing this table.
Alternative is to have two tables for keeping game stats, one being the header table, carrying attributes such as game session dates, duration, etc. and the detail table, keeping the game-specific attributes:
# pseudocode:
GameProfile
has_many :game_profile_details
end
GameProfileDetail
belongs_to :game_profile
stat_name: string
stat_value: string
end

You could create a generic model that holds the statistics for a given game.
Since each game would have some stats that are identical (name?, high score?) you could set those up easily.
The tricky part would be how to handle different game stats. One game might have a "best time" while another "turns used".
To handle this, you could save other data as a hash in a string.
So it would save meta_data: "{'best_time' => '0:04:23.6', 'other' => 'thing'}" in one game but you wouldn't need to leave an empty best_time field for games that don't use one.
Then when you load the data, based on the game, you could code
<%= #gamedata.meta_data.best_time %>
# returns "0:04:23.6"

Related

calculated fields: to store in DB or not to store?

I am building a ruby on rails application where a user can learn words from a story (having many stories on his list of stories to learn from), and conversely, a story can belong to many users. Although the story is not owned by the user (it's owned by the author), the user can track certain personal things about each story that relate to him and only to him, such as how many words are left to learn in each of his stories (which will obviously differ from user to user).
Currently, I have a has_many :through relationship set up through a third table called users_stories. My concern/question has to do with "calculated fields": is it really necessary to store things like words_learnt_in_this_story (or conversely, words_not_yet_learnt_in_this_story) in the database? It seems to me that things like this could be calculated by simply looking at a list of all the words that the user has already learnt (present on his learnt_words_list), and then simply contrast/compare that master list with the list of words in the story in order to calculate how many words are unlearnt.
The dilemma here is that if this is the case, if all these fields can simply be calculated, then there seems to be no reason to have a separate model. If this is the case, then there should just be a join model in the middle and have it be a has_and_belongs_to_many relationship, no? Furthermore, in such a scenario, where do calculated attributes such as words_to_learn get stored? Or maybe they don't need to get stored at all, and rather just get calculated on the fly every time the user loads his homepage?
Any thoughts on this would be much appreciated! Thanks, Michael.
If you're asking "is it really necessary to store calculated values in the DB" I answer you. No, it's not necessary.
But it can give you some pros. For example if you have lots of users and the users call those values calculating a lot then it could be more winnable strategy to calculate them once in a while. It will save your server resources.
Your real question now is "What will be more effective for you? Calculate values each time or calculate them once in a while and store in DB?"
In a true relational data model you don't need to store anything that can be calculated from the existing data.
If I understand you correctly you just want to have a master word list (table) and just reference those words in a relation. That is exactly how it should be modelled in a relational database and I suggest you stick with it for consistency reason. Just make sure you set the indices right in the database.
If further down the road you run into performance issue (usually you don't) you can solve that problems then by caching/views etc.
It is not necessary to store calculated values in the DB, but if the values are often used in logic or views its good idea to store it in Database once(calculate again on change) and use from there rather then calculating in views or model.

Rails model with multipe values for a field

I have a model Movie. That can have multiple Showtimes. Each Showtime is a pair of start and end times. Movies get saved in the database.
So although a Movie might have_many Showtimes, does that really need to be a model, or just a class, or some kind of custom tuple-like type?
I have seen where you can have a field with an array of values, but this would not be basic values as each value is a pair of times.
What is the best way to achieve this?
Showtimes should be a model, yes. Here are a few reasons:
Most relational databases don't natively support a tuple or array type.
What if you want to query movies occurring at a particular time? This would be difficult to do with a custom field, but would be relatively trivial with a separate table.
Most importantly, it enables better flexibility and extensibility through decreased coupling. For instance, does a showtime always exist exclusively to a movie? What if you want to extend your schema to add theatres where each theatre has many showtimes?

how to avoid empty fields in a database

Frustrated with the Active Record Reputation gem, which I found very buggy, I'm trying to make my own reputation system for a Rails app. It's very primitive. I created a Contribution resource with a user_id and a value field, with an association between User.rb and Contribution.rb. Every time a user contributes to the app in some way, they get some points. If they ask a question, these lines get included in the create action of the Questions controller.
#contribution = current_user.contributions.build({:value => 3})
#contribution.save
If a user edits some Tags on the site, I do the same thing to reward superusers for their administrative work
#contribution = current_user.contributions.build({:value => 2})
#contribution.save
It then becomes very easy to calculate a user's total reputation.
One problem with this is that, in an imaginary world where users care about this app and their reputation, it would be very easy to game the system. For example, a user could just keep updating the categories or tags, and every time they do so they get 2 more points. Therefore, I wanted to somehow record what type of action the user did.
Right now, all of the work users can earn points for is somehow associated with a Question.rb, however, they get points for updating Tags, updating Categories, upvoting other people's answers etc, therefore merely storing the question_id in the contributions model wouldn't be sufficient.
Based on what I told you, can you give me some idea how I might build out the Contributions resource in order to accomplish what I want?
For example, I thought of one way of doing it that would have left a lot of null fields in my database, so I assumed it wasn't a good way. I could add a question_id and several boolean fields such as 'answering_question' 'updating_category' 'updating_tags' and each time an action is performed, record with a 'true' whether, for example, 'updating_category' is being performed. However, as mentioned, if I start rewarding lots of different types of contributions, there's going to be a lot of columns in each row that aren't being used.
I'm not sure if that's a 'real problem' (i've read about it but not sure how necessary it is to avoid), or if there's a better way of recording what type of activity each user is engaging in to earn points.
some of the current associations
User has_many :answers
Question.rb has_many :categories
Question.rb has_many :tags
for my rails application I am using thumps_up gem which is better than active_record_reputations_system ,Its more simple.
https://github.com/bouchard/thumbs_up

Creating new workout journal/tracker app need help establishing database/models to get started?

I am fairly new to Ruby and Rails, made a few blogs etc. I am slowy learning the ruby language and rails framework. I am wanting to create a workout journal/tracker application and need help establishing the models and or to get me started on the right path. I basically want to be able to create a workout/different types of workouts (back, arms, legs, etc), be able to use the # of sets and reps used for that workout, how many days/which days a week, add, edit, delete the workouts, track weight loss/weight, track the workouts, reps, sets you did prior, set goals in the journal, track progress, eventually be able to share workouts etc. I know what I am looking to do just need help getting started and establishing what models to use and what associations to use. I know it seems like alot of info. Any help getting at all getting going would be awesome. Thanks all!
This might be a bit tricky, since there are many styles of exercises -- N sets of M reps, pyramid, max lifts, etc. You may want polymorphic associations in the final version.
But I think you'll have a more clear vision of where to take the project once you've built a few tables and classes; I think I'd start with a Workout class that has_many WOSets (don't use Set; having class names that conflict with built-in class names is way more irritating than you may think), and each WOSet has_many Reps. Then your Reps will keep track of count and weight. Store the order of the reps in the WOSet.
You'll also need a Station class for all the machines and exercises; probably your WOSet will belongs_to the Station, and the Station will has_many WOSet. (So you can retrieve all the sets ever performed on a specific station.)
I hope this quick sketch gets you to the point of playing with creating new workouts, new stations, and playing with the interface in script/console.
Models = Tables
You should have a look at database design and normalization. Its paramount you get the basics right. Otherwise you might end up with database with common errors like performance issues and redundancy (which is is a bad thing).
One you understand what it is you need to store, mapping it to Rails is easy.
http://en.wikipedia.org/wiki/Database_normalization

Model design -- What's the optimal way to do this?

I have this app I am writing in Rails 3.1, I am wondering the best way to model this.
Would it be best if I created a model called "Movie" with a "title" and then create a new model for each "movie asset" such as "poster, trailer, screener" etc and relate it to the "Movie" by associations? Or would it be best if I just created this as one and do-away with the of associations of each asset to "Movie"?
My assumption is to just make it as one as it will remove all the overhead of the FK's and joins to get retrieve the data related to the movie but I am looking for opinions/suggestions. Thanks
There can be three types of attributes(columns) for movies.
Which have exactly one value, and are present in every movie e.g. title, year, official trailer etc.
Keep them in the movie table.
Which have exactly one value, but are present in few of the movies e.g. total Academy Awards.
Keep them in separate table, and use has_one+belongs_to association.
Which have multiple values e.g. trailers
Keep them in separate table, and use has_many+belongs_to association.
More suggestions:
For many key-value attributes, it is easier to use one json/yaml column using serialize instead of creating one column for each key.
Do not store images in DB, keep them in file-system or cloud storage.
You can create your models in the order you want since you have to fill in both models to create a unique association (such as belongs_to and has_many) so I think it doesn't really matter !

Resources