|
I think it all depends on where the logic is placed. Controllers shouldn't have much business logic in them, but moving logic out of a controller or a model isn't necessarily better if it's done in an obfuscationary way. The problem is that the patterns provided by Rails and suggested by the Rails community encourage "needless indirection" more than they do actually managing logic in a sane way. Concerns, though they definitely useful for some things, end up becoming dumping grounds for loosely-coupled application logic. I know that the same could be said for just creating modules without ActiveSupport::Concern, but the existence of ActiveSupport::Concern seems to have suggested to a lot of Rails developers that the de facto answer to fat controllers and models is to just dump excess logic into these "concern" modules. ActiveRecord in itself is another fundamentally flawed concept in Rails because it treats data and the interface to that data as one in the same. Models become dumping grounds for a ton of seemingly data-oriented behavior that probably better exist as helpers. I like the idea of ActiveRecord, and I seriously loved it when I first learned Rails, but every Rails project I've encountered contains these needlessly fat models with lots of overridden/custom attributes(that could have been helpers), callback after callback, etc. An alternative example exists in Ember Data, where the data and interface are split between concepts: The "model", the "adapter", and the "serializer". This keeps the logic around data very well organized and interoperable(i.e. switching adapters). Models in Ember can still have custom attribute getters, but I still say that it's best to try to avoid those if possible and instead look to creating helper functions first. I guess the point of what I'm saying is that Rails developers think too much in terms of object-orientation, which leads them down the path of thinking about relationships in a way that encourages bloat. In other words, the mindset becomes that where if some behavior has to do with the concept of a Post, for instance, then that behavior should belong in the Post class(without taking much account into whether that code only involves the view or data persistence). Logically, it makes sense from an OO point of view, but then you're going to end up with a pile of code in one place that you will inevitably extract into a "concern" which you'll have to "include" in other models that share said behavior. Often times, just creating a set of functions/methods is simpler and more understandable. They don't have to be a part of a specific model or a class, but just be available when needed. In Rails, most of the time that's the view, sometimes the controller, so helpers in Rails are perfect for that. Helpers are contained in modules, but with the way they are integrated into the application, you don't have to think much about that. Business logic that is more complex or falls outside the scope of helpers should go into Ruby code that doesn't depend on Rails, but can just be imported and used within a Rails app. This not only creates a separation between business logic and the logic of rendering HTTP responses, but refraining from making all your code Rails-centric means that the business logic should be easier to test in isolation and faster without all the overhead of Rails. |