Rails Model for flexible points system - ruby-on-rails

I am trying to design the points system for a game application, and having some issues figuring out the best way to setup the models. The basic needs are:
Each user can be assigned essentially a "PointsCalculator" object, responsible for keeping track of the points that the user is earning
Each user's "PointsCalculator" logic could potentially be different. For example, one user might earn an extra 100 points every time he plays for more than an hour consecutively. Another user might earn double points between the hours of 8PM and 10PM.
We are trying to figure out the best way to create a model setup that will allow us to store logic that can be customized for each user, but is still DRY and testable.
I don't need anyone to write code for me - I would more just appreciate the feedback of more experienced developers, or anyone who has tackled a similar issue in the past.
Note: Above has been edited for additional clarity, but let me know if it is still unclear.

Difficult question which depends on your complexity level:
If all Points Calculator are well defined, you should head towards Single Table Inheritance (STI). The most simple case.
But if much flexibility is demanded, this becomes harder and you should consider the inclusion of methods dynamically, a la DCI. It's the most complex. See details below.
Ex: you store a list of calculator behaviors in a serialized object within your model:
behaviors = [ 'behavior1', 'behavior2' ]
Each behavior is linked to a class or module with the same name, eg: Behavior1 and Behavior2.
Then you add behaviors to your object on the fly whenever you need them, for instance in an after_initialize.
after_initialize :set_behaviors
def set_behaviors
behaviors.each do |b|
self.extend(b.constantize)
end
end

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.

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

A model with a handful of id's

I have a model which has many of another model but this model only needs to have 10 or less id's in it.
Let's say it has, Bathroom, Kitchen, LivingRoom for arguments sake and the new records will probably never need to change.
What is the best way of making a model like this that doesn't use a database table?
This may not be best practices, but to solve the same problem I just specified a collection in my model, like this:
ROOM_TYPES = [ "Bathroom", "Living Room", "Kitchen" ]
Then in the view:
<%= f.select(:room_type, Project::ROOM_TYPES, {:prompt => '...'}) %>
(replace Project with your actual model name.)
Super-straightforward, almost no setup. I can see how it would be difficult to maintain though, since there's no way to add items without accessing the Rails code, but it does get the job done quickly.
Even though the collection of rows never changes, it's still useful to have this as a table in your database in order to leverage ActiveRecord relations. A less contrived example would be a database table that has a list of US states. This is highly unlikely to change, and would likely have only a couple of columns (state name and state abbreviation). However, by storing these in the database and supporting them with ActiveRecord, you preserve the ability to do handy things like searching for all users in a state using conventional rails semantics.
That being said, an alternative would be to simply create a class that you stick in your models directory that does not inherit from ActiveRecord, and then either populate it once from the database when the application loads, or simply populate it by hand.
A similar question was asked yesterday, and one of the answers proposes a mechanism for supporting something similar to what you want to do:
How to create a static class that represents what is in the database?

Performance issues with complex nested RoR reservation system

I'm designing a Ruby on Rails reservation system for our small tour agency. It needs to accommodate a number of things, and the table structure is becoming quite complex.
Has anyone encountered a similar problem before? What sort of issues might I come up against? And are performance/ validation likely to become issues?
In simple terms, I have a customer table, and a reservations table. When a customer contacts us with an enquiry, a reservation is set up, and related information added (e.g., paid/ invoiced, transport required, hotel required, etc).
So far so good, but this is where is gets complex. Under each reservation, a customer can book different packages (e.g. day trip, long tour, training course). These are sufficiently different, require specific information, and are limited in number, such that I feel they should each have a different model.
Also, a customer may have several people in his party. This would result in links between the customer table and the reservation table, as well as between the customer table and the package tables.
So, if customer A were to make a booking for a long trip for customers A,B and C, and a training course for customer B, it would look something like this.
CUSTOMERS TABLE
CustomerA
CustomerB
CustomerC
CustomerD
CustomerE
etc
RESERVATIONS TABLE
1. CustomerA
LONG TRIP BOOKINGS
CustomerA - Reservation_ID 1
CustomerB - Reservation_ID 1
CustomerC - Reservation_ID 1
TRAINING COURSE BOOKINGS
CustomerB - Reservation_ID 1
This is a very simplified example, and omits some detail. For example, there would be a model containing details of training courses, a model containing details of long trips, a model containing long trip schedules, etc. But this detail shouldn't affect my question.
What I'd like to know is:
1) are there any issues I should be aware of in linking the customer table to the reservations model, as well as to bookings models nested under reservations.
2) is this the best approach if I need to handle information about the reservation itself (including invoicing), as well as about the specific package bookings.
On the one hand this approach seems to be complex, but on the other, simplifying everything into a single package model does not appear to provide enough flexibility.
Please let me know if I haven't explained this issue very clearly, I'm happy to provide more information. Grateful for any ideas, suggestions or comments that would help me think through this rather complex database design.
Many thanks!
I have built a large reservation system for travel operators and wholesalers, and I can tell you that it isn't easy. There seems to be similarity yet still large differences in the kinds of product booked. Also, date-sensitivity is a large difference from other systems.
1) In respect to 'customers' I have typically used different models for representing different concepts. You really have:
a. Person / Company paying for the booking
b. Contact person for emergencies
c. People travelling
a & b seem like the same, but if you have an agent booking, then you might want to separate them.
I typically use a => 'customer' table, then some simple contact-fields for b, and finally for c use a 'passengers' table. These could be setup as different associations to the same model, but I think they are different enough, and I tend to separate them - perhaps use a common address/contact model.
2) I think this is fine, but depends on your needs. If you are building up itineraries for a traveller, then it makes sense to setup 'passengers' on the 'reservation', then for individual itinerary items, with links to which passenger is travelling on/using that item.
This is more complicated, and you must be careful to track dependencies, but the alternative is to not track passenger names, and simply assign quantities to each item (1xAdult, 2xChildren). This later method is great for small bookings, so it seems to depend on if your bookings are simple, or typically built up of longer itineraries.
other) In addition, in respect to different models for different product types, this can work well. However, there tends to be a lot of cross over, so some kind of common 'resource' model might be better -- or some other means of capturing common behaviour.
If I haven't answered your questions, please do ask more specific database design questions, or I can add more detail about specific examples of what I've found works well.
Good luck with the design!

Howto "virtually" create and save an attribute of a separate model in rails

The title may appear as if I am asking howto access/find/update an attribute of a related/nested model but this is not the case and unfortunately this is the best title I could figure out.
I would like to build a soccer management game with ruby on rails, where routine total_attack_value and total_defense_values are matched etc. I don't plan to make the simulation too deep like in here and here, such as calculating and matching separate corner_attack or side_attack values but seriously intend to include the goalkeeper's skill in total_defense_value.
To clarify, the total_attack_value is going to be calculated as "total_shooting_value x total_pass_value x total_possess_value x/+ Rand() etc" and all of these ..._values are going to be calculated inside the Team model but the total_defense_value should have "goalkeeper_skill_value" which is going to be the skill of the player selected as the goalkeeper by the user for the coming match, as I planned.
I cannot think of anything else than saving and retrieving which player is put into goalkeeper position by the user using virtual attributes, since the user is going to schedule the match for a future time and the goalkeeper selection should persist until then. In this case I'm going to create a Player_Position model and an association model belonging to both Position and Player and an assign_positions function in Player model etc. However this is exactly what I am trying to avoid, code- and complexity-wise being the same as to offer the user the possibility to drag&drop players to positions separately as seen in some games like soccermanager and goalunited.
Does rails offer any simple/ready solution to this problem as it does to simple CRUD operations, like an attribute or STI?
I'm not sure if I completely understand what you are trying to achieve but the next version of Rails, 3.2, has simple Key Value Store functionality that you may be able to use. The release candidate is already out so you would be able to try it out to see if it met your needs.
A short note on the functionality was included in the latest release notes.

Resources