RoR; Third party library wrapper for specific needs with service object - ruby-on-rails

Is there any best practice to where third parties wrapper libraries are settled on rails application?
I've been developing with app/service driven way, so it's easy to encapsulate the action behind the scenes.
Ref: http://brewhouse.io/blog/2014/04/30/gourmet-service-objects.html
Now the problem is
Where should I put third party library wrappers for specific needs?
For example,
Mailchimp: wrapper for email subscription
Prawn: The wrapper for PDF receipt
Slack notifier
....
I could create gems for each ones, or put them into models.
If the code is big enough such as PDF receipt wrapper, I could go for creating gem, but if it's small I don't think it's good to put neither model/gem.
Any suggestions?

It's really up to you.
You can put custom code in new files in config/initializers - these will be required automatically.
It's also common to put code in lib/ and add it to the autoload path (there are other questions for this).
You could make a model for each service as well. You don't necessarily need a database table for models (there are other questions for configuring this).
I think this information (where to put custom code) is really integral to rails and I see a lot of beginners confused by it.

Related

Organize External API Calls in Rails 4 - Module or Class?

I am creating a Rails app that will use quite a few external APIs such as SalesForce, FolderGrid(like Dropbox) etc., which would all sync to my database. I've never worked with external api calls so I created a few basic Ruby scripts with scattered methods to test the call to those resources. Now I would like to implement them with my full Rails app.
So far, I started off by creating a directory in my /lib folder for holding the api call modules/classes..
/lib/apis/foldergrid.rb
Now I'm not sure what the best approach would be towards organizing the code. In my standalone Ruby scripts, I have methods for authenticating, creating a folder, auditing files, downloading files etc.
What should be in a Module? Do I even need a Module? What should be in a class? How do I make sure I can use these methods in my models and controllers where needed? Is there a best practices concerning external APIs?
Any resources, links, and/or deeper understanding is highly appreciated.
I have an app that does this too (pulls data from multiple APIs) so I can tell you what I would did (or in some cases what I would do now if I was to start over).
Data Storage
First off if you are already persisting the data pulled from those into a Rails app, then you will have models representing the data themselves. So that's what you would refer to in your controllers unless your controller is in charge of calling the APIs.
Use Gems where possible
Second make sure to leverage existing gems that existing for the APIs so you're not recreating the wheel of authentication, parsing the JSON to and from the app, etc. For example: there is a rest-force gem for salesforce.
Use Ruby Objects in Lib for mapping between your models and API responses
Third, I would make the classes that map data in between API responses and your models into "Plain old ruby objects" and store them in a lib/apis folder (no need in these cases to store in a module, yet IMHO). They might end up very functional and in the case of mapping data, that is ok.
APIs without existing Gems
In those cases, I would definitely keep them in one or more classes under a module, in their own folder in lib. That way you can parse them out if needed as a Gem (or if you to take the time make them a Gem to start with, I'm sure others could benefit). I just started down this road myself this week using Infoconnect's API which didn't have a Gem (or any code samples in any language). But I'm not very far along.
If needed, create service objects for code in between V and C (view and controllers)
If you do end up needing to do anything to interact with users for the API information or anything that calls those request, I would put those in service objects so your code doesn't get bloated in the view or controller.
What should be in a Module?
A module should contain code that is shared by different classes, or it can be added to a single class.
Do I even need a Module?
No, you can achieve the same thing with inheritance. If there is no code to share, then you probably don't need a module.
How do I make sure I can use these methods in my models and controllers where needed?
You can access them using the class from within a controller:
SalesForceAPI.get_data
"Module or class?" is an age-old question in Ruby, and any other language that supports both.
I would encapsulate the functionality for each API in a class. For example, you can have a SalesForceAPI class. Then, if you need to share functionality between the classes for authenticating, creating a folder, auditing files, or downloading files, you can create an API class.
Each of the classes that needs access to the API class would inherit from it:
SalesForceAPI < API
You can achieve the same thing by creating an API module, and mixing it into the other classes. In this case, it's largely a matter of preference, because either solution is good.
FWIW, I don't know if there would be much shared functionality for authenticating, creating a folder, auditing files, or downloading files, because each API can work quite differently. However, if they are REST API's then you may create some REST helper methods and put them in the API class.
A great, easy to understand, and complete resource on the topic is Practical Object Oriented Design Ruby.

Rails: Re-using models, controllers and even views between Rails applications

I have a rails app which contains some fairly generic functionality (eg managing users). I would like to use that common functionality in other rails apps without copying it. The hard part seems to be that this code contains a number of models, controllers and views.
I know that gems and plug-ins allow code to be shared but they seem to apply more to sharing utility and library functionality rather than core parts of an app.
Any advice on how to do this would be greatly appreciated.
We are working with a Rails engine to share functionality between client projects and have gotten quite far with it. The engine contains controllers, models, views, and even routes. It provides core functions needed in each project (access to our in-house content management system) so projects don't have to start from scratch.
Most of the code has been structured in a way that it can be easily extended or overwritten where needed in the projects (mostly by subclassing). It's distributed as gem.
I can't show you code (it's not open-source), but I can point you to some helpful resources:
Rails 3 Plugins - Part 1 - The Big Picture
Rails 3 Plugins - Part 2 - Writing an Engine
Rails::Engine documentation
Plugin Authors: Toward a Better Future
Hope this helps!
Making copies is not always bad. That's why I ask about the reasons you don't want to copy the code.
If you create a 'library', you must ensure that every application will use it in the same manner. Or you have to prepare the 'library' for every possible difference between your applications which use it.
If you share the code, you are adding a dependency to your program. Any change in that shared code will affect more than one application.
Often it's much simpler to copy the code to another application, because then your may apply any modification without thinking about others.
Are you sure that managing users is so generic that you will not make any application-specific changes to it?
What about creating links to the files/directories that have the MVC? That is better than making copies.

Helpers in rails

I'm just starting out in Rails and there's a lot I still need to learn so I'm likely to be on Stackoverflow more often than normal asking beginner Rails / Ruby questions.
I'm just trying to figure out how Helpers work in Rails. From what I've seen so far, Helpers are intended to be used with Views and not so much with your Controllers.
However I would like to make a simple function that will validate the user input given in params (check if certain params are defined and optionally check if their value is valid).
Can anyone explain to me what would be the best way of implementing this? (Keeping in mind that I will want to use this in many different controllers so it should be globally available.)
I also noticed that by default Rails does not generate a lib folder in the main application folder. Are developers to place their libs outside the app folder in the main folder, or does Rails use libraries differently?
With regards to your validation issue, it depends on what you are validating.
If the data makes up objects from your problem domain, also known as models, then you should use the built in validators from ActiveModel. This is probably what you should do, but its hard to say without knowing the exact problem. See the Rails Guides on Validations. You can tell if this is the case by asking yourself if the data that needs validation will be stored after you get it. If so, its most definitely a model. An example of this kind of data would be the title and text fields of a blog post being sent to Rails from a browser form.
If the data is something tertiary to your models, or specific to presentation, then you should be fine using helpers. You noticed that helpers are used mostly in the views, and although this is true, theres nothing stopping you from using them in the controllers, you just have to declare that you will use them using the ActiveController#helper method. Inside the ApplicationController class, a lot of devs will put helper :all to just include all the helpers in all the controllers. Once the code has been required once, it doesn't really incur that big a performance hit.
Do note that almost all incoming data can be modeled using a model. A big school of thought in the Rails world subscribes to the Fat Model idea. People say that putting as much code as possible in the model and as little in the controller as possible separates concerns properly and leads to more maintainable code. This suggests that even if you don't think the incoming data is modelable (in the sense that you can create a model to represent it), you should try to make it a model and encapsulate the logic around validating it. However, you may find that making a helper function is faster, and either will work.
Your notion of validating user input is a good one. I get the feeling that as you are new to Rails you are used to doing these things yourself, but that doesn't quite apply here. In the Rails world, a lot of the common stuff like validations is handled by the framework. You don't have to check for presence in the params array, instead you call validates_presence_of on the model and let Rails spit the error out to the user. It makes things easier in the long run if you let the framework do what it is designed to.
With regards to your question about the lib folder, it doesn't really matter. You can put miscellaneous support files and libraries in the lib folder in the root directory and they will be available for use in your application (the files in the app folder). You can also choose to abstract your code into a plugin or a gem and include it that way, which a lot of people opt to do. My suggestion for this would be to read up on the notion of gems and plugins before diving in.
Want you want is probably a custom validator (in Rails3):
http://railscasts.com/episodes/211-validations-in-rails-3
You can either add libs in a lib folder you create, or add them to config/initializers in a file you add. Files in the initializers directory are automatically loaded by Rails.

Rails: Where do you put non-model code?

I'm new to Rails, and have been learning with Rails 3 on a side project. There are times when I want to write some code that does not belong in my models or in my controllers - concerns that are related to a model and/or controller, but i don't want to clutter up either of them with the implementation details of what i am writing.
For example: a project i'm building uses Janrain's authorization system (RPX) so i can get oauth, openid, google, etc. authorization. there's a nice chunk of API code that they provide so i don't have to write it all myself. this code doesn't belong in the login controller or in the user module. it's authorization code, so it needs to be accessible by the login controller, but it's not part of that controller.
Where do you put this code? it's not model code. it doesn't belong in the controller.
... thanks in advance.
You should be able to use lib folder in your root directory (unless it's changed in Rails 3).
You can refer classes from there without require statement.
A 'common' suggestion is to say 'put this stuff in lib'. But there are other places to consider:
Consider making a subfolder in app. Some examples include: app/workers, app/observers, app/sweepers, or whatever makes sense for you.
Consider using config/initializers for initialization code.
Lastly, and only if the above don't make sense, you can use lib. Don't forget you can use subfolders to keep it from getting too junked up.
And, once you get things working and polished, consider extracting your code into gem. See, for example, the RailsCast on Creating a New Gem with Bundler.

Does a "vertical" framework for RoR make sense?

I have been spending some time creating what I called a framework.
It was aimed at the creation of quiz likes games. It was supposed to have two players syncronized and present them a question to solve, etc.
I would like it to be fully customizable so I tried to develop components that can be put in or out of the pages. In the end the elements became slim ruby methods to add a whole bunch of Javascript and CSS to the pages.
Still the Javascript needs to connect to Ruby so methods supporting it are created but they will only be present when the component is present. Some components depend on one another making everything overly complex.
And after this attempt I wonder, is there is not a better and easier way to make a framework aimed to one kind of application on RoR? Or is the concept flawed or RoR in some way flawed?
Ruby on Rails is a framework on its own accord and is "opinionated software". This means that the writers of Rails looked at what would make most sense for creating a web application to them. Many people support the original developers views and so use Rails for their projects as well.
I think your concept of creating a quiz is a good one, but first you need to understand the rails stack. Depending on what you need exactly, you can create either an engine, plugin or whatever.
What I have seen a lot is that you specify what you need in your controller. (How you do that is up to you). All that information is stored in a class variable and transferred to the view where you can render everything you need with some helpers. The hard part is making it all generic enough to be reusable.
But, maybe Rails isn't the right tool for you. Maybe you need something more lightweight like Merb or even Sinatra.
There is no 'flaw' in Rails. Rails is not the 10**1000-in-one tool Java is. It's a framework that tries to do one way very good in a particular way. I think Rails can be the right tool for you, but you need to be skilled enough to wield the tool :)

Resources