Modeling data for complex applications: inheritance? modules? - ruby-on-rails

I'm developing a prototype for a Rails application that has a somewhat complex model. I'm having a hard time figuring out how the model should be designed.
Here's the basic idea:
Say the app is for a small coop, and should allow users to file "applications" (as in a apply for a loan, accounts, etc) online.
Technically, all of them are "applications" and my client would like a dashboard presenting all pending evaluations for a given group (ie: the auto loans group). So, I'm thinking of having an application model. I could subclass ApplicationModel for loans, accounts, etc., but I'm thinking Rails will use a Loans table, an Accounts table, and so, and so for each type of model. There are different kinds of loans too: Mortgage, Auto, Personal, etc. All require different data. A manager for the whole Loans division, should be able to see all pending loan approvals from his dashboard (all classes of loans).
If I were to do something like Loans.find() would I get all Loan subtypes with it? Or only what's stored in the loans table?
Is inheritance the way to go? Should I be looking at something else? Is rails even adequate for this kind of application?
I saw the legacy application built on Java that they were using (but hated with a passion). The previous developer had an ST_APPLICATIONS table which store all applications. In that table he stores all the application data in a blob containing a bunch of XML. Would such an approach be recommended with Rails?

Related

What is the name of this concept I am implementing, and how to in Rails?

I am trying to implement a feature to my project (kind of like a social media site) that could be either basic or complex and I am not sure if I am going to take forever reinventing the wheel or just go on a crazy tangent that won't work. I just need to "check in" so to say.
I am going to use Facebook terminology as an example to simplify the concept but implement similar features with different names. In Facebook you have Pages and Groups, which are similar yet have slight differences (from now, I will call the collection of these DataSets). Both of these can have multiple admins or followers, which are all User roles, and each User can have roles for multiple Groups and multiple Pages (one role per Group or Page). Then for example, you can click a drop down to change your account to post as a Page you are an admin for.
Essentially, the concept I am describing is where a single User can have a role for multiple different types of DataSets. For example, a single User could follow 30 different Pages and 10 different Groups, and be an admin for one Group and two Pages. Does the concept I am describing belong to a particular concept or software design pattern? I am finding it really hard to describe this feature without using Facebook examples.
I have a strategy to implement this type of functionality in Rails, but I feel like using this strategy would be making the problem harder than it is and there is a fancy rails way of doing it, or a Gem, but I just don't know how to research it due to lack of terminology to describe my problem.
Current strategy is:
I have a Users table from Devise. Pages and Groups are each individual models and have their own tables. I have matching database tables to make the many-to-many relationships between Pages and Users, along with Groups and Users (e.g. 3 column design, column for the user_id, column for the page_id and the type of relationship such as admin or follower). Let's call these Group_User and Page_User. I am being flexible at the moment as I may add more DataSets similar to Page and Group.
Then for the Devise User table, I have an extra two columns to track the DataSet that the User is an admin for and currently posting as. One column is for the DataSet type and the other for the id for this instance (e.g. [Group,1] is stored in these two columns to represent Group with group_id:1 and [Page,3] is used to represent Page with page_id:3). These two columns can be checked when displaying options relevant for admins in that Group/Page and a simple drop down at the top of the site changes the values in these columns to any of the Pages/Groups the logged in User is an admin for. This way, one User login can take on many admin roles and change between these easily as needed.
Is there a better way to do this in Rails, such as a gem or specific design pattern? Or am I on track to implement these features myself? I think I understand the problem but my solution just seems simple/raw and possibly might have unintended consequences later down the track (e.g. it seems database intensive).
One way I was thinking of doing this was making a concern that includes methods to build the relationships and pass in the name of the DataSet as an argument, just so I am not rewriting the same methods for Pages, then Groups, then whatever comes next.
I looked at other solutions such as polymorphic typing (which I think is good for if each user only had one role or only managed relationships for one group or one page) and Single Table Inheritance (but I think my Pages and Groups might be too different for this to work). I thought about using inheritance as well (e.g. a parent for both Group and Page) but I am not sure this helps much.
I am just a guy that studied too much computer science and not enough software engineering. Any tips on how to simplify this problem or just a simple "yeah that will work" would be really helpful!
I think you are going great in the database design. Once participated in a social media application like yours which had similar type of design. Your design seems much better than the one I worked with. In my opinion this type of applications are supposed to be database extensive.
There are several design patterns used in RoR. One I heavily use is Service Object Pattern to maintain thin controller and models. Also it helps me to write reusable class.
Another one I like is the Presenter Pattern to simplify views.
You can have a details look at this blog post for more design pattern ideas.

Role based authorizations or different tables in a ruby appointment booking app

I have seen regular debates about the way to manage the different class of users.
Usually, it seems that developers prefer a role based approach (e.g. user, admin,...) with gems like Cancancan
But I'm wondering if it's applicable for an appointment booking app (appointment for doctors, teachers,... or even bookings). Indeed in this case, the 2 types of users have access to totally different pages. In its documentation about associations, Ruby on Rails guide takes the example of a medical appointment booking app with 1 table for doctors and 1 table for patients.
For this kind of app, I'm a little bit lost regarding the most efficient solution!
Thanks!
You can use a tool like Cancanan to break out the different roles and abilities, then restrict access to certain parts of the system based on those rules.
Additionally you can display only the relevant navigation or pages when the user's accessing the system so they might not even be aware of what they're not seeing.

Database design for reverse-auction platform

The idea is for a reverse auction platform where users post their auction for certain services and providers bid on it with their offers.
Should I be splitting my tables? For example the auction can be for a new service or to replace an existing service so there are questions that are specific to each selection.
Should I move those columns into a separate table for that option?
Here is a diagram of what I've come up with so far:
Database Diagram image
Am I on the right track here?
What data type should I use for columns where there will be an list of options to choose from in the auction form? For example, cash_back will give the user a range of choices as:
Donate to Charity
Deposit to my account
Credit Voucher
Is the norm to use a string for this column with the respective strings or do I create a new table for the options and use the option_id as a foreign key in this table?
I think it is worth discussing here Rails philosophy and database design generally.
As I often say you can have a database for your application, or you can have an application for your database. In the latter, database design is important. In the former, it usually follows application design.
What this means is that you probably, assuming this is a Rails app, don't want to design your database at all. What you want to do is design your application object model and let Rails design your database. You won't get a great db design that way, but it will be good enough.
The tradeoff is that when you go this way, you often end up with the database as effectively owned by the application and it may not be safe to have other apps add or modify the data in the database. Moreover it may be harder to come up with really good reports, but where you put in most of your time will be better optimized (your main app).
TL;DR: If you want a database for your app and using Rails or Django, then stop thinking about database design, but realize that while this optimizes some pathways today, it makes many other things harder down the road.

Multi-tenant rails application: what are the pros and cons of different techniques?

I originally wrote my Ruby on Rails application for one client. Now, I am changing it so that it can be used for different clients. My end-goal is that some user (not me) can click a button and create a new project. Then all the necessary changes (new schema, new tables, handling of code) are generated without anyone needing me to edit a database.yml file or add new schema definitions. I am currently using the SCOPED access. So I have a project model and other associated models have a project_id column.
I have looked at other posts regarding multi-tenant applications in Rails. A lot of people seem to suggest creating a different schema for each new client in Postgres. For me, however, it is not much useful for a new client to have a different schema in terms of data model. Each client will have the same tables, rows, columns, etc.
My vision for each client is that my production database first has a table of different projects/clients. And each one of those tables links to a set of tables that are pretty much the same with different data. In other terms a table of tables. Or in other terms, the first table will map to a different set of data for each client that has the same structure.
Is the way I explained my vision at all similar to the way that Postgres implements different "schemas"? Does it look like nested tables? Or does Postgres have to query all the information in the database anyway? I do not currently use Postgres, but I would be willing to learn if it fits the design. If you know of database software that works with Rails that fits my needs, please do let me know.
Right now, I am using scopes to accomplish multi-tenant applications, but it does not feel scalable or clean. It does however make it very easy for a non-technical user to create a new project provided I give them fillable information. Do you know if it is possible with the multi-schema Postgres defintion to have it work automatically after a user clicks a button? And I would prefer that this be handled by Rails and not by an external script if possible? (please do advise either way)
Most importantly, do you recommend any plugins or that I should adopt a different framework for this task? I have found Rails to be limited in some cases of abstraction as above and this is the first time I have ran into a Rails-scaling issue.
Any advice related to multi-tenant applications or my situation is welcome. Any questions for clarification or additional advice are welcome as well.
Thanks,
--Dave
MSDN has a good introduction to multi-tenant data architecture.
At one end of the spectrum, you have one database per tenant ("shared nothing"). "Shared nothing" makes disaster recovery pretty simple, and has the highest degree of isolation between tenants. But it also has the highest average cost per tenant, and it supports the fewest tenants per server.
At the other end of the spectrum, you store a tenant id number in every row of every shared table ("shared everything"). "Shared everything" makes disaster recovery hard--for a single tenant, you'd have to restore just some rows in every shared table--and it has the lowest degree of isolation. (Badly formed queries can expose private data.) But it has the lowest cost per tenant, and it supports the highest number of tenants per server.
My vision for each client is that my production database first has a
table of different projects/clients. And each one of those tables
links to a set of tables that are pretty much the same with different
data. In other terms a table of tables. Or in other terms, the first
table will map to a different set of data for each client that has the
same structure.
This sounds like you're talking about one schema per tenant. Pay close attention to permissions (SQL GRANT and REVOKE statements. And ALTER DEFAULT PRIVILEGES.)
There are two railscasts on multitenancy that using scopes and subdomains and another to help with handling multiple schemas.
There is also the multitenant gem which could help with your scopes and apartment gem for handling multiple schemas.
Here is also a good presentation on multitenancy-with-rails.
Dont forget about using default scopes, while creating named scops the way you are now works it does feel like it could be done better. I came across this guide by Samuel Kadolph regarding this issue a few months ago and it looks like it could work well for your situation and have the benefit of keeping your application free of some PgSQL only features.
Basically the way he describes setting the application up involves adding the concepts of tennants to your application and then using this to scope the data at query time using the database.

Rails: model vs. array

When should an array of values become a full fledged model? My problem is an application that is littered with models for such mundane objects as Country, Degree, Profession, etc. which are all simply parts of a user registration form. Should these constant arrays just be hard-coded or is there another better way to store them than using ActiveRecord models?
If it makes sense to have them as database tables, then it makes sense to have them as models. And I would argue that it does make sense to have at least some of these as database tables, because that way you can give your client the ability to edit them on-the-fly. I don't want a programmer to be responsible for maintaining a list of countries or professions.
(In a recent application I worked on that had an international focus, the ability for the client to edit the list of countries was a key requirement; in many settings, what countries are listed and what they are named have controversial political implications, so the client needed domain experts to discuss and decide on country names.)
Hardcoded Array is fine, creating a model for this is part of the antipatterns listed in 'Rails Antipatterns' from Chad Pytel

Resources