DesignPattern for Attachments in a Chat with carrierwave - ruby-on-rails

User should be able to send some pictures to his chat partner (whatsapp/line style).
There might be a possibility to also add other attachments and videos. We having an argue about the model structure. We are using carrierwave to manage the files. right now, the user can only send Pictures, in future there might be some other datatypes to be added.
Solution 1
pretty standard imo, having 3 classes (each has own DB table) and each class is getting his own carrierwave-uploader.
Chat::Picture
Chat::Video
Chat::PDF
Solution 2
this might be a little bit more trickier. Instead of 3 Models we are only having a Chat::Attachment and by that we use STI to define the type.
Chat::Attachment::Picture < Chat::Attachment
Chat::Attachment::Video < Chat::Attachment
Chat::Attachment::Pdf < Chat::Attachment
here also every class is getting his own uploader.
So the Question:: is this the right spot to use STI as a design pattern or should we stick to regular rails-models?

The answer depends on how much change you expect in future. If you expect more changes in future then you should go for rails usual way. I personally dont like STI much. I think you will be better off not using STI here, rails will provide you better separation of concern here. STI should be considered when dealing with model classes that share much of the same functionality and data fields, but you as the developer may want more granular control over extending or adding to each class individually. Rather than duplicate the code over and over for multiple tables (and not being DRY) or forego the flexibility of adding idiosyncratic functionality or methods, STI permits you to use keep your data in a single table while writing specialized functionality.

Related

Sharing AR models between Rails applications

I have a problem that I have been trying to solve for a while now. I have 4 different Rails applications using the same database, meaning they need to use the same models and have the same migrations. I initially solved the problem by creating a Rails engine packaged into a gem, which then carries all the models and migrations with it. Now I realize that there are pieces of functionality that only one application needs, but the others do not - like for example the admin application needs to have methods for providing sortable tables for all models - the other applications do not need this functionality at all.
So my idea was to find a way where I can provide the "base" models from the gem, while augmenting these base models in my specific applications to add additional functionality when needed. What I tried first was inheritance:
class User < Base::User
end
This does not work though, because now you have 2 User models in your load path (User and Base::User) and when querying associations, it always picks the "closest" class for the associated record class - meaning when you have an Model::Account which belongs_to :user, it will pick Model::User as the association class, not User. I tried reversing the AR type compute method but this only resulted in more problems.
I can technically provide all of my models from the base engine (gem), but the issue here is that how do i extend these models in my application? .class_eval feels really really dirty, inheritance does not work, providing base functionality as mixins means the "base" models do not feel and look like models at all. My goal would be to cause as little friction as possible for the other developers, I want them to be able to define their models in the gem like they do normally and then also have an easy way to extend that functionality in other applications.
Has anyone solved this problem before or have any suggestions? Or how do you guys solve this problem in your larger applications? Any help would be appreciated.
This is mentioned in the Rails guides. It describes class modification with the Decorator pattern.

Models in Rails are implicit, is this an annoying thing?

Considering models in Rails:
class Organization < ActiveRecord::Base
belongs_to :OrgType
end
Does it bother you that models in Rails don't include the fields that made the entity?
I know this is done for DRY's sake but you have to check the data base tables schema every time you want to check model's fields.
If you prefer a declarative style of ORM model, you might want to check out DataMapper or Sequel, both of which are easy to plug in to Rails 3.
Not annoying for me... ever since I started using the annotate-models gem to automatically add comments to the top of my model files, listing the fields associated with that model.
I was listening to a podcast a few months ago where the guy hosting the cast and the guest were advocating that Rails should take this path, and do away with migrations. The guy kept repeating "migrations must die", suggesting there be a way to specify your schema on the model instead.
I cannot disagree more, and I hope Rails never takes this path. Not only is it not DRY, but I like the fact that Rails encourages you to be aware of your own databases schema and structure.
In addition, there would be no way to keep a history of your schema if models were what controlled it, without having them be extremely cluttered. Migrations are essentially version control for your database that evolves with your application...and I wouldn't want to not have that.
Let's assume that OrgType has a field called position. This is common when you want to present a select list to the users who will be choosing a type. It's highly unlikely that your Organization will ever care about this field. Now extrapolate this to other related models with fields that other models don't care about, and add in the fact that if you ever wanted to change one of these fields you'd then have to hunt down each declaration of them, not just each place where they are used.
It's a mess.
Open up your db tool and look at your fields when you want to know what they are. Keep your models clean and readable. If you see code like this:
organization.org_type.name
It's pretty obvious that OrgType has a name field, without having to look it up, and without having to wade through configuration clutter in each model.

Rails: When a model? When a lib?

I'm making a little message sending module. It'll handle queuing messages from a request to be picked up by a background worker to send email/SMS (or log appropriately for testing).
Question: is this a Model (under /app/models) or a lib (under /lib).
I'd like some religion on this.
Theory A: (My current theory) Unless you're subclassing ActionMailer::Base or ActiveRecord::Base, etc, your code should go into lib.
Theory B: (Theory I'm leaning towards) Things that are application-specific should be in model. Anything that could be of general use should be in lib.
Theory C: only "data models" should be in 'models'. ActionMailer subclasses break this rule, though.
As far as I know, either way it'll work fine, but I'm looking for any subtle functional or philosophical reasons for one vs. the other.
Thoughts?
Whether or not messages inherit from ActiveRecord or ActionMailer, you likely want a model for any objects that your views and controllers interact with. In your case, they will handle instances of the Message class -- you want a model for that.
As for the message sending module -- extracting out to a library is great if you plan to reuse the code elsewhere where you can just include the module in any class.
Since this is just a "little" message sending module, you might want to start in the model and eventually extract out to a separate module if it could be useful elsewhere or your model gets too messy.
You should probably think more in terms of the underlying business here. Models, as their name suggests, are here to represent (model) some real-world system or process. So, the rule of a thumb should be this: Does this entity play any role in the system I'm trying to express in my application? If the answer is positive then the entity is a good candidate for being a model. However, it'd be perfectly OK to implement the core functionality of your messaging module in some separate library for later reuse and just include it in the model.
I like the 'Data Model' Theory and I try to stick to it when I can, but I think Bensie and Milan have the right idea. If you have views and controllers associated with it, it should be with models. If you are only referencing the functionality from within another class, put it in the lib.

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.

Is this a legitimate use of Rails' Single Table Inheritance?

I've just been reading Chad Fowler's blog post about 20 Rails Development No-Nos. On Single Table Inheritance he comments:
The storage of a column called “type” which holds a class name is a pretty good indicator that something fishy is going on. It’s fishy but not always bad. I think, though, that any time you use it you should ask yourself more than once if it’s the right solution. Databases don’t do what they do best as well when you have lots of STI and polymorphic associations.
I'm writing a blog application and I'm considering using STI for the comments that can be made on a post and for the contact messages that visitors can post if they want to get in touch with me. My Message model will inherit from my Comment model. They both share common attributes, except that Message will have an extra subject field. Another commonality is that both will be submitted to Akismet for spam checking.
Rather than just ask myself more than once if it's the right solution as Chad suggests, I thought I'd get some opinions from the Stack Overflow experts as well! Does what I'm proposing sound like a good fit for STI?
I've used STI a number of times. Consider a CMS which might have Page, NewsItem, BlogItem etc.
They could each descend from a common class which in turn inherits from ActiveRecord. The table for each would be the same (title, body, tags, published_at) but each model might have different associations, or different statuses, or a different workflow so each has custom code in their own class. Yet they all share a common table and parent class. It also allow me to use the parent class to do a cross class search and have the resulting Array of records automatically type cast.
There are other ways to tackle this and maybe not the best example but there are certainly times when STI is handy for situations where object behavior may differ but persisted state is the same. Of course you have to be sure this is also true in the future.
In your case comments and contact messages are different. It sounds like there is there no benefit by having them in the same table. Maybe put shared code in a parent class or better still in a module in /lib.

Resources