Ruby on Rails: Should a single field ever get its own model? - ruby-on-rails

I'm new to Ruby on Rails. I have a relatively simple question. I'm modeling users. I want users to be able to have a short "profile message" that they can edit and that gets displayed on their profiles. Would it make sense to make ProfileMessage its own model? Or, should profile_message be one column in a table that contains user settings?
I feel like an entire model just for one string is a little bit overkill and if I start going that route, I'm going to end up with so many models that things become cumbersome.
What does the community think?

I would keep your data structure as simple as possible when starting out. For a profile message, it doesn't make much sense to have it be it's own model. Only if profile_message were to later on have it's own set of attributes and behaviors, or if users could have more than one profile message...then I would consider moving it to a separate model.

Table joins in SQL consumes a lot of resources when you are not using them properly. In your case i think that making a new model only for the one profile_message is not a good practice.However, it should be implemented inside the user/profile model.
This approach is going to make accessing the message faster, on the other hand if you are using a whole table for the profile_message will make the response time slower because you will need to look for it every time in the profileMessages table which will take more time depending on the number of entries in that table.

Related

Data model and storage for Rails app

At the moment ’m building a web app using Ruby on Rails. I try to get my head around the data model and database part. To make it easy to understand I’ll use IFTTT as an analogy:
In the app, the user can add different recipes, for example:
Facebook — Twitter
Weather — Send email
You name it...
Of course every recipe has its own fields and options. So the user can choose multiple recipes from the library and set options to every recipe. The library of recipes is defined in code.
I have a few questions regarding this setup and would be happy if I could get some directions:
Is it smart to serialize the options of a recipe into a single database field? Every recipe has different fields and I don‘t want a database table for every recipe type.
Or is it better to create a ‘key-value’ table with all the options of all the recipes?
How to handle validation? Can Virtus come in handy?
Is a NoSQL database a good fit for these kinds of applications?
Are there best practices for these kinds of applications/data models? Any help is welcome.
Thanks!
Rens
Not sure if SO is the best place for really general questions like this but I'll take a swing
1 && 2) Personally I'd give the recipe table an action_taken field, probably as a string, and fields for all the available, resulting actions as booleans. Then the only thing you really need to be careful of is making sure the action_taken field remains uniform
3) ActiveRecord has a pretty fleshed out validation suite built in. You can validate based on presence, uniqueness, inclusion in a set of elements, etc. You can also extra validations on the database if you feel like being extra safe
4) I would use PostgreSQL, seems to be the community standard so probably the easiest to get support with if you need it
Hope this helps

Sanity check my Rails "Roles and Users" approach with Devise and Cancan

been kicking this one about for a while now, and would like to get someone who knows rails to test my theory (I'm new to Rails).
In my (simplified) scenario, I want to manage a list of Users, some of which are, for example, "paid" users, some are "free" users etc, and there is a straight "isa" relationship. i.e. a paid user isa user, a free user isa user etc
To reduce redundancy and to keep it semantically correct, I want to manage all the users in one table and use a foreign-key back to the correct "type" of user, so I can create a role of the correct type. e.g. I would instantiate a User, get the id and store this in the user of correct type e.g. "PaidUser" in the "user_id" foreign-key. This gives me the ability to store specific metadata I want to store against them, and I don't have to have one table ("users") with every field for every type of user.
This sort of feels like a confusion of roles and types of users. My question is, is using the approach above going to make life difficult? Is there an accepted approach to this in Rails that I'm missing? I'm using Devise and have removed all routes except for /users/ thinking I would pass a "type" as an argument, and use that type to create the corresponding "real" type of record at the same time as the user. Is this bad practice too?
Thanks in advance
What you're doing sounds fine, but to be honest unless you have a lot of these different properties between user types I would just put them all in the same table. It's not really a big deal to have a couple of blank columns here and there, especially when it saves you from having to do a whole load of difficult stuff. If this starts to seem unwieldy then you can worry about what to do then - it would still be easy to change. You could even then potentially use Single Table Inheritance to give all the different user types their own class that inherits from the base User class, which is where you take care of all the authentication etc.
If you immediately go with something more complex then it will be much harder to unravel if it turns out to be wrong than if you start with something simple. If you go with the multi-table approach then make sure you name them sensibly. I would go with PaidUserProfile etc.

Deciding between using an array attribute or a nested model

Possibly a fairly basic question, but bear with me.
I'm building a page which has a number of pieces of modular content, represented by a ContentBlock model. Each ContentBlock has at least one link, each of which has a couple of different attributes. My initial approach was to just add these links as an array to the model, as there didn't seem to be any real need to store them separately in the database, and they don't have any logic of their own. Now that I'm looking at building a form for creating/editing a ContentBlock though, it seems like it would be much easier to build if there was a separate, nested model for the links.
I'm strongly considering converting to using a model, but my gut feeling is that it's kind of "wrong" to store something like as relatively trivial as the links are in the DB. Given I am still getting used to working with Rails, is this feeling misplaced? Should I just create models for anything and everything? Or should I be looking for some sort of minimum criteria before I do?
It is definitely easier to create forms for nested models. Since your links have attributes, I'd suggest making a model. I tend to err on the side of making models for concepts that can't easily fit into fields. If you're worried about query performance, you can always do eager loading.
I think depends on how much data you plan on managing, what you want to do against that data, what that data represents, etc...
One project we had was to build something that allowed creation of recipes for a group of restaurants. Recipe (some text, like instructions, etc...) -> Ingredient, we went with an array, as these were all single lined text and there would never be more than several hand fulls. Also, the ingredients had no further dependencies. The Recipes would only be rendered out to html and there would be no searching against them (not against the db at least).
Another project required building a Page, very similar to yours, but each "component" of the page did different things and some where linked to other objects in the app, like Videos and other assets, templates, etc... We had seen people do this type of stuff entire through a wysiwyg or through some JS way and saved the entire payload/structure in the DB. We found both to be extremely messy.
And one concern that came up was what happened if an asset/associated object was mistakenly or purposely deleted but lived throughout many pages. Using models allowed to ensure that if something got removed, it got removed within all it's linked associations (though this posed problems of it's own, but more regarding the page making sense when displayed more than anything else).
Also, our Page had the potential of becoming extremely large with different types of components with different looks and inter-activities, that this really was the only way we could properly manage it.
So I would look at your requirements and plan accordingly, context matters. And if you have to change it (which happens, a lot) then you'll change it.

RoR table inheritance?

Scenario: I have a users table in my application. I also have two subclasses of users, lets say contributors and viewers. Each user group must have an entirely different set of attributes but they both share certain user properties (login, password, name).
What is the best way to implement this using Ruby on Rails?
I think single table inheritance would leave me with too many null fields.
I think linking three tables (users, viewers, contributors) would work fine, but then when wanting to edit any information i have to do: #user.viewer, while i would love to be able to just do #viewer.
Any ideas of the best solution?
I would probably go with the three tables approach. Data integrity is king over code cleanliness.
If you want to make it look neater, put virtual attributes on the Viewer and Contributor models that make it look like the User attributes are local. You can make it a module and include it in both Viewer and Contributor models.
You can also set up an :include => :user on the default finders so that you don't get an extra query when using those fields.
I'm extremely caffeinated right now, so comment back if that doesn't make sense :)
don't compromise the database schema, make it fit best. I like the three table method. If you do the database bad, the application will have very hard to fix issues later, run slow, etc.

Considering a new Rails app with existing data (not a db, actual data) -- what is the best way to proceed?

I have been tasked with developing a new retail e-commerce storefront for my current job, and I am considering tackling it with RoR to A) Build a "real" project with my limited Rails knowledge, and B) Give management quick turnaround and feedback (they are wanting to get this done ASAP and their deadlines are rather unrealistic - I'm talking a couple of weeks to go from nothing to working model so they can start to market it with SEO/SEM and, I kid you not, "video blogging" because my boss heard that's the future).
We do have a database structure in place but it's absolutely terrible and was thrown together without rhyme nor reason, so I'm going to largely ignore it and create a new database from scratch; however, I have existing data that I need to load into the application (like I said, it's an e-commerce app and we have the product data). I need to massage this data into a usable format because our supplier provides it to us with cryptic, abbreviated column names and it's highly denormalized, especially in the categories (I've posted a question regarding it before - basically the categories table has six fields, one for each category/subcategory, with some of them being blank if that category doesn't apply).
There are two main issues that are giving me second thoughts:
As I said the data needs to be put into a "proper" database schema; I can't just load it as-is. I have some thoughts as to a good data model for it, but my analysis is not completed yet. There would end up being a large amount of joins tables to link various things together (e.g. products_categories, products_attributes, products_prices) etc and these tables would link products not via an ID but by their SKU (see below).
Everything already has an ID that's generated for it, but anything new I add needs to have one autogenerated; I doubt this will be a problem with any mature RDBMS, but I know Rails likes to generate IDs itself. Also, almost all of the product-related tables are linked by SKUs (and in the data provided by the supplier are actually a composite key consisting of the prefix and stock number, which combined make up the full SKU), not by IDs and I'm not sure if this will be a performance issue (of course, I could always manually create indexes on these columns to speed it up). It does mean that I'll need to break away from the Rails conventions, however.
In short, I think that Rails might be a good choice as far as time-to-market and ease-of-development, but having to work with the existing data content might turn into a pain because the application will need to be developed around that, instead of the "traditional" Rails app, and that factor is giving me major doubts about using Rails. There are also some other issues (having to set up a Linux server, and the fact that the area I live in has very few Rails developers so if I left the company I'd basically be holding them hostage as far as updates/modifications). I'm really unsure as to the best path to proceed.
I would develop the app as if you didn't have the data. Use the ORM and make your database the best it can be, but of course keep in mind what data you have to populate it with (eg: don't make crazy new constraints for things that will leave you going through old data record by record).
When you're done and tested, write an import script that pulls your real data onto your new database.
It's not that different from the conventional design/development model... Apart from you can do your data-input in a semi-automated fashion.
I was in the same situation not too long ago — a crappy PHP app that held ten years worth of all company data.
What I did was simply create a Migration model and added methods to import each resource.
class Migration
def migration_all
self.jobs
end
def self.jobs
...
end
end
The cool thing about this is that you can arrange which order resources are imported as one will likely reference another. I also added methods that directly modified the db schema. One nice trick if you have to keep an existing primary key is to create a field named 'legacy_id', copy over your existing primary key, and when you're done, simply remove the 'id' field, rename the 'legacy_id' field to 'id', then add the primary_key constraint on the new 'id' field.
Don't use the SKU as the unique key for each product - use the standard Rails incremented id.
SKU could change as it may be misentered, etc and that would make it a nightmare to change all of the references from other tables. Put your current id in a sku column, index it and update the references in your other tables to the Rails ids.
You'd be able to do Product.find_by_sku(params[:sku]) in your controllers, set up a /products/:sku route, etc. I don't see what you'd gain (other than a headache) by using your non generated ids as the database primary keys.
I'd also suggest running your old data through your app's validations to make sure you are not loading up a bunch of inconsistencies and erros. It will help your app run smoothly and highlight existing data errors at a point where you can fix them.
Don't assume the existing data is valid just because it is already there.

Resources