Need suggestion for Ruby and Rails coding standards - ruby-on-rails

I am developing my application using Rails. It has 400 or more models and some models contain more than 200 rows just for relationships, so it's too hard handle it. Are there any ways I can handle my application in more proper and easy ways?

In application that I'm working with, there are about 100 models. Few things that helped us develop it:
you can create hierarchical directory structure to models. It is obvious when talking about controllers, but for models it's not that straightforward
you can split models into logical parts by putting chunks of code into modules
doing above two points sometimes allows you to see some ways to refactor your code. Some modules might become common between models. Some things can be excluded into methods that will dynamically generate common parts of models
sometimes modules handle unnecessary logic, and that makes harder to understand them -- if your methods contain lots of cases or ifs to handle different types of objects (like admin/normal user) probably you should use polymorphism
refactor, refactor, refactor ;-)
Wise refactoring takes a lot of time, but if you drop this part of development, project maintenance will become overwhelming. Check out books about Ruby, RoR, refactoring, metaprogramming. Investing time in learning might also bring effects.

Related

Best practice for multiple resources and one database table in ruby on rails?

I'm working on a Ruby on Rails project. The project has a main database table, called 'Post'.
This table is used for storing questions, answers, comments and announcements as different post types. Currently we use only one model to access the data. But while working on the systems it feels cluttered. Because every post type has some differences.
What is a best practice:
Split the post resource into different resources, but using only the one Post table for data access?
Split the database table into comments, questions, answers and announcements tables; and use resources for each table (model+controller+views)?
Short answer: it depends.
What you're doing now is pretty close to Single Table Inheritance (STI), though it sounds like you're using a single Post class which contains all your different behaviors. STI is a valid approach to storing your model data, but like everything, it has advantages and disadvantages.
My recommendation would be to use separate classes to encapsulate the behavior of separate domain models. This is the fundamental paradigm in OOP, so I would say it's probably a best practice.
Assuming you split your behavior across classes, the question of whether you use a single table to store them or multiple tables really depends on the complexity of your queries and how many common fields there are across your models. If they share a lot of common fields, STI may work nicely. If not, you're probably not going to enjoy the overhead of all the extra reads/writes you'll pay. But all that is really secondary and can be figured out as your app grows and you learn more about the usage patterns.
Try it using STI and see how it goes. Splitting things up into multiple tables is easier than the opposite, so a migration path is not necessarily too hard.
I think the choise should be based on every certain situation. Just enumerate advantages and disadvantages of each option for you. Points to investigate and make decision could be like: number of differences between each type of entities, the way to access entities, frequency of usage of each type of entities, maintability of code, forecast of changes in the future, and many others.

How to refactor a Rails model that contains significant amount of back-end code?

I have a Rails 2.X model with 421 lines of code/comments that does a significant amount of work on the backend (opening HTTP Get requests, parsing RSS, parsing HTML, etc.). At the same time, I'm moving to Resque in order to more quickly get through this backend code. I'm wondering what the best way to refactor this would be. Should I move this back-end code to a library that I include in the model? A module? A gem?
Your thoughts would be much appreciated.
I basically have a separate core tasks for each data item i'm processing. i.e. parsing an RSS feed, parsing a HTTP URL, running regex on that html body, as well as a few other tasks and right now i have 500 or lines of code within the model; even though most of the stuff the model does is called through a back-end script run by cron
So to make it more wieldy and to make it easier to move to resque; i was thinking of doing separate classes for each resque queue, and using static methods there
Then I can require those classes by the back-end 'controller' script if you will... Does this approach make sense?
Your best bet from a testability and thought process standpoint is probably to break out those various concerns into their own (non-ARec) models. You might have RssParser, HtmlParser, ServiceRequest, etc., based on your first paragraph.
Depending on where this stuff is used (multiple projects?), it might make sense to make your own gem and version it.
I have written big and small resque classes before, and you'll save yourself a lot of pain if you make the resque classes as thin as possible.
The model in question is doing many things.
In a well-structured application, every class does one thing and does it well. This feature of a well-structured application is part of what makes it highly testable.
You should break apart the many things that the one model does into multiple self-contained classes, keeping the dependencies between them minimal. Then you will be able to test each of those new classes easily, and you will have a number of new stub points to test the overall model.
In my experience, if this code is going to be used in more than one application, maybe a gem is worth considering. Otherwise, adding the layer of indirection by moving the code to a gem doesn't seem to yield much benefit. In fact it can potentially slow down development depending on your deploy situation.
As for how to re-factor the model, look through all the model's code and as yourself the question "What is this model doing?". If you end up with lots of 'and's or 'or's, then you should probably strive to make each item delimited by 'and' or 'or' its own class (see http://en.wikipedia.org/wiki/Single_responsibility_principle). Breaking out the responsibilities in this manner makes the individual concerns much easier to write tests against. Especially when making external HTTP api calls, etc.

The "Right" flow in creating a Rails project

I'm starting out with Ruby on Rails and I know of a few stuff already, but I was wondering if there was a "right" way of going about developing a project. Right now, I would create my models first using [script/generate model MyModel] then modifying them until I feel they are complete enough. Then I'd go for [script/generate scaffold MyModel] so I don't need to do as much coding for the views. Lastly I modify the views and add more models then scaffold some more for other features I might need.
Would there be a better way of doing this? Especially in the context of working with a team in developing a project? Thanks!
I'm sure everyone has their own workflow, but I think a typical one is this:
Specify the "domain" your project. This probably sounds silly, but before you get started you should really think about what exactly your website is going to offer. It doesn't need to be specific down to the last detail, but should have an idea so that you can perform the next step...
Design your database schema. I usually just plan this out on paper. There's a real art to creating a normalized database. Think of everything that needs to be "permanent" in your app, because it will have to be in the database and accounted for, with as little duplication as possible.
After this I usually do as you say: create my models (and migration scripts along the way). The main thing you want to get down in your models first is the associations with other models.
The next part depends on how comfortable you are as a developer in Rails. A lot of people enjoy the test driven development approach (TDD), and will write Unit tests (Rails provides excellent facilities for writing these, and rake tasks to run them). However, since you're just learning, you may want to write your tests after you implement your model business logic.
The road after this is pretty much up to you. You can work on your views/controllers/models as you need to. That's one of the beauties of Rails and agile development, you don't need a lot of boiler plate code to get started.
I'm probably weird in this, but I usually design my front page and get some basic CSS going, as I find I am more productive if my results are semi-nice looking.
I would probably avoid generating scaffolds though...I think you'll learn a lot more about the framework and spend less time removing unwanted code if you generate the individual pieces themselves.
In the context of developing with a team, things will probably be different. If you have a lot of complex business logic, some people may spend most of their time writing model code, while people more on the design side will be implementing view code. But you will have to meet in the middle of course, which will get easier as your project grows and becomes more modular. Just remember to use a version control system! Subversion if you want something easy to use and learn, Git if you're up for a challenge.

Do we use Rails ActiveRecord as a Hybrid Structure, i.e. Data Structure+Object?

I have been using Rails for over 4 years so obviously I like Rails and like doing things the Rails Way and sometimes I unknowingly fall to the dark side.
I recently picked up Clean Code by Uncle Bob. I am on Chapter 6 and a bit confused whether we as rails developers break the very fundamental rule of OO design, i.e. Law of Demeter or encapsulation? The Law of Demeter states that an object should not know the innards of another object and it should not invoke methods on objects that are returned by a method because when you do that then it suggests one object knows too much about the other object.
But very often we call methods on another object from a model. For example, when we have a relationship like 'An order belongs to a user'. Then very often we end up doing order.user.name or to prevent it from looking like a train wreck we set up a delegate to do order.name.
Isn't that still like breaking the Law of Demeter or encapsulation ?
The other question is: is ActiveRecord just a Data Structure or Data Transfer Object that interfaces with the database?
If yes, then don't we create a Hybrid Structure, i.e. half object and half data structure by putting our business rules in ActiveRecord Models?
Rails is Rails. What else is there to say. Yes, some of the idioms in Rails violate good design principles. But we tolerate this because it's the Rails way.
Having said that, there is far too much model usage in most rails applications. Far too often I see view code directly accessing models. I see business rules folded into the active record object. A better approach would be to isolate the business rules from the active records and isolate the views from the models. This wouldn't violate any rails idioms, and would make rails applications a lot more flexible and maintainable.
IMHO if you follow the purist approach too much then you end up in a mess like Java where it uses all the right design patterns but no-one can remember the eight lines of code you need just to open a file and read its contents.
Rails' ActiveRecord framework is an implementation of Martin Fowler's Active Record design pattern. Active Records in Rails are certainly not just dumb data structures or DTOs because they have behaviour: they perform validation, they can tell you if their attributes have changed etc. and you're free and indeed encouraged, to add your own business logic in there.
Rails in general encourages good practice e.g. MVC and syntactic vinegar to make doing bad things difficult and/or ugly.
Yes, ActiveRecord deliberately breaks encapsulation. This is not so much a limitation of Rails as it is a limitation of the pattern it's based on. Martin Fowler, whose definition of ActiveRecord was pretty much the template Rails used, says as much in the ActiveRecord chapter of POEAA:
Another argument against Active
Record is the fact that it couples
the object design to the database
design. This makes it more difficult
to refactor either design as a project
goes forward.
This is a common criticism of Rails from other frameworks. Fowler himself says ActiveRecord is mainly to be used
...for domain logic that isn't too
complex...if your business logic is
complex, you'll soon want to use your
object's direct relationships,
collections, inheritance and so forth.
These don't map easily onto Active Record.
Fowler goes on to say that for more serious applications with complex domain logic the Data Mapper pattern, which does a better job of separating the layers, is preferable. This is one of the reasons that Rails upcoming move to Merb has been generally seen as a positive move for Rails, as Merb makes use of the DataMapper pattern in addition to ActiveRecord.
I'm not sure Demeter is the primary concern with ActiveRecord. Rather I think breaking encapsulation between the data and domain layers breaks Uncle Bob's Single Responsibility Principle. Demeter I think is more a specific example of how to follow the Open/Closed Principle. But I think the broader idea behind all these is the same: classes should do one thing and be robust against future changes, which to some degree ActiveRecord is not.
Concerning "Law of Demeter" one thing I've not seen mentioned is the concept of distance. By that I mean, "How closely related are the object involved?" It is my opinion that this would make some difference whether I care to follow "Law of Demeter" or not.
In the case of ActiveRecord, the objects involved in most of the LoD violations are inseparably bound together into a close relationship. Changing the internal data structure of these objects require a change in the database to reflect that new structure. The tables of a database are typically "bound" together into a single database, which even reflects these "associations" through foreign key constraints (or at least contain primary & foreign keys).
So I don't generally concern myself with following LoD between my AR objects. I know that they are tightly bound to each other due to their very nature.
On the other hand I would be more concerned about LoD between more distant objects, especially those that cross MVC boundaries or any other such design device.

Single table inheritance and where to use it in Rails

I am stuck in a weird Design problem,
I am working on a two type of profiles Models,
User profile (belongs to User)
others that are maintain in-site as "bots" (doesn't belong to anybody)
The typical OO behaviour of these two types of Profiles is same but only the important attributes/properties are common ( the very important ones 5-6 in number), others properties like "interests etc"(almost 10-15 properties) are not there for bot profiles
The coder who worked on this earlier created separate models/Controllers for bot profiles / User profiles which creates a lot of redundancy everywhere and also as expected hard to maintain, write tests etc.I wanted to DRY this up, atleast to solve some/all of these redundancy problems.
Somebody suggested Single Table Inheritance as a solution
Somebody suggested Use Polymorphic Associations instead.
what is the better approach. When do we actually use STI?
My own thought was STI is used best when attributes are same for Models and they differ in behaviour.
Thoughts about what can I do?
Characterising STI as mostly useful when attributes are the same but behaviour differs is "about right", but possibly a little limiting. I like to use STI when there is, as the name suggests, a clear OO-style inheritance relationship, rather than the database-style relationship between objects of different types.
If there is common code between bots and users, I'd say STI sounds like a winner. If there's just some common attributes, it's probably less applicable but still worth having a go at.
I'm a pretty experimental person, so my recommendation is to give it a go. Branch your code and refactor the models into an STI relationship. See if it really does dry things up, or just swaps one set of headaches for some other problem.
One thing I think you won't see much benefit from is drying up your controllers. In my experience, STI models don't often translate into similarly related controllers. But that would be something else to experiment with. Sometimes there's a win, sometimes there isn't.
I've written an article on this very topic, including some tips for working with STI:
Single Table Inheritance in Rails
In short: there needs to be a clear OO-style inheritance relationship among objects (as eloquently stated by womble), not just some shared data. If there isn't a natural and obvious class hierarchy, a STI design may become difficult to maintain as your application evolves.
Secondly, you should consider if it's important to have all the data in one table. With polymorphic associations, your database queries will become more complex, and probably slower. If you're planning on listing all the objects together on the site (eg, in a table) then STI may be the way to go.
Thirdly, make sure your child classes don't have too many unique attributes. With all the data in one table, you don't want a lot of non-global columns. Not only do these take up space (not a major concern), but they make the data structure confusing. If you do have "special" columns you should explain them explicitly in your code.
Lastly, if you do use STI, I strongly recommend using a single controller for all of your child models. The main function of a controller is to provide access to objects, and if the objects need to be accessed in very different ways, then STI may not have been the correct design choice to begin with.
Check out my article (link above) for some more useful tips.
I would probably use either STI or no special features at all. You might be able to call everything a Profile and you'd know if it was a "bot" if its user was nil. You could also store a "type" field without using STI.
Certain things would affect my decision to use STI:
Whether there is bot-specific logic
How many bots there are versus users profiles (small number of bots means STI is OK - lots of bots and I might store them somewhere else)
The reason to avoid STI is sometimes it can get in your way. For instance it can be fairly annoying to change an object from one type to another (a Bot to a Profile in this case). Sometimes a simple "type" field is better.
Its worth noting that you'll probably want a common base class if you use STI. So you may want Profile, BotProfile, and UserProfile. The names are up to you. :)
One gotcha of Rails STI - most plugins (and so forth) don't support it fully. You will find yourself patching many of the common ones.

Resources