Is it a good practice to namespace jobs? - ruby-on-rails

Is it a good practice to namespace jobs?
In my application I have two jobs that are related to the Page model - both of them are going to receive a post_id and perform a specific task there. The jobs are called PageWritingScoreJob and PageArchitectureScrapingJob. I want to use the namespace Page instead: Page::WritingScoreJob and Page::ArchitectureScrapingJob, but not sure if that's a bad practice.
thanks

There is no real reason why using namespaces would be a bad practice.
In Rails apps everything is generally lumped in the global namespace not necessarily because it's the best way to do it - it just convenient.
It's a widely accepted that placing code in the global namespace is problematic when it comes to interoperability as it greatly increases the risk of name collisions. This is especially true in Ruby which lacks a import system like that in Python or Ecmascript. That's why almost every gem incapsulates it's constants in a module.
In a rails app though you are most often the end consumer of the application code which means that placing your controllers and models in the global namespace works well enough that it's often worth the trade-off of simpler code templates and not having your code intended an additional step and nested in an additional folder.

Related

Why Model View Controller in their own namespace?

This might be a bit of a noob question, but I'm curious why the convention for MVC classes is to be in their own namespace, eg
namespace WebApplication1.Controllers
and not
namespace WebApplication1
Is there a good syntactical reason for this or is it just to improve readability?.
Is it perfectly ok to not follow this convention and use the same namespace for the whole project?
You can use namespaces any way you like, as long as it makes sense to you.
What they've done there is simply a convention deriving from the separation of concerns part.
Are their disadvantages to this method? Well yes, separate too much and your classes become a mess with too many using statements.
If you put too much under one namespace that can also cause issues because you don't know exactly what's available to you and it makes finding anything difficult.
If your namespaces follow your folder structure then it can help keep your code nicely organised and everything is easy to find just by looking at the namespace.
It is possible, but namespace are there for minimizing classes name conflicts, which if you handling middle+ projects you will encounter.
More on Namespaces
They also help the Intellisense display current available entities, but this is just a bonus and not the actual target of name spacing.

Manage module trees with ActiveSupport

I have a Rails project MyApp which I fragmented into multiple gems. One of them is to manage users.
Considering that I want code reloading and auto-require from ActiveSupport, along namespaced folders to require files. I can organize my code this way:
# MyApp::Users
./lib/my_app/users
./app/controllers/my_app/users/
./rspec/unit/my_app/users/
The above way is the most clean one, but results on long nested routes with the repeated pattern my_app/users/, which can be exhausting for lazy programmers. Since I still need the folder namespace to differentiate code from different gems, I thought about abusing the root namespace:
# Users
./lib/users
./app/controllers/users/
./rspec/unit/users/
That is not as clean and the more I fragment into gems, the higher my chances to have a namespace collision.
Which organization pattern is the most commonly used? Which is the Rails way?
For a library the first one seems the best one, but for a large application it feels tiring having all the time long paths and maybe the fear for name collision is doing more harm than good.

When should you nest model declarations in Rails?

What are the guidelines about when it is better to nest Model name spaces and when it is better to leave them all top-level?
For instance, when I have a few classes that all have something to do with one core class (and the majority of the system only deals with that core class) then my instinct tells me to declare them as such:
CoreModel
CoreModel::DependentOne
CoreModel::AnotherDependent
Almost always this corresponding to has_many/belongs_to relationships (i'd almost consider this the next candidate for convention over configuration.)
And again, my routes often reflect this nesting:
/CoreModels/:core_model_id/DependentOne/:id
The reason I feel like I should do this is because often two component areas of the same large application may need a supporting component with similar if not identical names as other areas of the software. I feel like name spacing these dependent models (which only exist to support that core model) is the best way to go.
I'm confused because while some times doing things this way can make stuff easier (such as link_to which needs only to take the DependentOne model and will automatically route correctly) yet other items such as form_for refuse to work properly (because it doesn't route properly and if I add the CoreModel to the form_for it complains about no such route core_model_core_model_dependent_one etc....
Perhaps I haven't been clear enough and so I'll ensure I update this as requests for clarifications come in.
...the majority of the system only deals with that core class...
In that case, I wouldn't bother namespacing them.
The reason I feel like I should do this is because often two component areas of the same large application may need a supporting component with similar if not identical names as other areas of the software. I feel like name spacing these dependent models (which only exist to support that core model) is the best way to go.
Bingo - if you have name conflicts, namespacing is a good way to fix it. But, do you have that problem yet?
Namespacing prevents name conflicts, but in Rails it also introduces some gotchas and headaches and (throughout the app) quite a bit more typing. So, to me, it isn't worth it unless you actually have a name conflict.
Consider a structure like this, with your core model and many that just help it.
#Core Models
Model
Supporter
Assister
Helper
Benefactor
For most of the life of your app you may never run into a problem. If you do finally hit one, you could just do this:
AltModel
AltModel::Supporter
OtherModel
OtherModel::Benefactor
Or if it's really simple just prefixing the class name would work:
AltModelSupporter
OtherModelBenefactor
For that matter, it's probably simpler to name your core models in this way than it would be to "properly" namespace them:
CoreModel
CoreSupporter
CoreAssister
So, there are many ways to accomplish what you need, none of which suggest you should bother namespacing the core functionality of your app when you don't actually have a namespace conflict. Given the headaches you've already run into I think you'll be happier leaving the core models of your app in the top-level namespace and only nesting alternate models that actually have a conflict down the road.

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.

Help me with my architecture - global variables in Ruby on Rails

I'm thinking about global variables in my rails application. I've searched the net about that, and found it (of course) flagged as a bad practice. I already knew that.
But I have not found another way than a global variable for what I need. Can an experienced Rails programmer help me ?
What I want to do is to create a new dedicated logger, for example logging to "log/audit.txt" and share it between several controllers. Of course, I would rather not have to recreate this "logger" object for every request.
For now, I create a logger in a global variable $my_logger in an initializer, and use it across my controllers.
What do you think ? Is there a better way to do that ?
Thank you.
The general OO stance against using global variables and singletons of any type -- in Rails and in all other OO habitats -- is to avoid the "slippery slope" towards not doing OO design at all. Global variables are to be avoided as much as possible, but your logger is obviously a case where a Singleton of some sort makes sense. The Rails environment is an example: you only have on Rails environment per application, and it's essentially a Singleton. Or consider Notifier.deliver...
Don't worry about where to put it if it must be global. Make a Singleton object with class methods as accessors and put it in lib or anywhere you think is appropriate (making a plugin might also be appropriate, for instance). Then you just use Logger.instance.log whatever. Of course you'll have to put in safeguards to make sure that the thing gets instantiated only once.
This SO question is extremely relevant: In Ruby on Rails how can I persist objects in memory between sessions
If you use the accepted answer, you'll be able to keep the logger in memory in production mode across requests.
However, I like the second answer...
to quote:
I wouldn't worry too much about
loading and discarding objects unless
you can come up with a benchmark that
proves it's an issue. Each request
creates an extraordinary amount of
intermediate objects as a matter of
course, and these are generally
created and destroyed in a matter of
several milliseconds.
...
Benchmark first, optimize only when
required.
Create your own custom logger class and require it when applicable.
Example here:
http://ianma.wordpress.com/2009/04/08/custom-logging-in-ruby-on-rails/

Resources