Inheritance services Ruby on Rails - ruby-on-rails

So I'm learning RoR and I have to 3 services that calls an API with the same structure and i want to know if i can do it with a parent class and then work with the parent class to save code.
Thanks!

Yes. This may work if you can define a method with fewer arguments, which builds that structure for the API call.
Approaches are:
Put that common method in a base class which the other classes inherit from.
Put that common method in a module as a mix in.
Write a class to handle the call to the API, which builds the structure.
I don't think you have an "isa" relationship from the sound of it. So unless you do, 2 is preferred to 1. You can only inherit from one class, so mixins are more flexible.
Approach 3 is a good idea. You can have internal methods for the hostname and other constants for your API call.
This can be combined with the other approaches as you can use the Aggregation pattern to aggregate the API object in the other classes. That might or might not make sense. It might be just as well as the other classes have methods which instantiate the class in approach 3 and call it.

Related

Creating and storing generic methods in ruby on rails

I'm making a method inside a Ruby on Rails app called "print" that can take any string and converts it into a png. I've been told it's not good to make class methods for base ruby classes like String or Array or Hash, etc. so "some string to print".print is probably not something I should do.
I was thinking about making a subclass of String called Print (class Print < String) and storing it in my lib/assets folder. So it would look like: Print.new("some string to print"). So my question is, am I on the right track by 1) creating a sub-class from String and 2) storing it in lib/assets?
Any guidance would be greatly appreciated!
Answers to your question will necessarily be subjective because there are always be many answers to "where should I put functionality?", according to preference, principle, habit, customs, etc. I'll list a few and describe them, maybe add some of my personal opinions, but you'll ultimately have to choose and accept the consequences.
Note: I'll commonly refer to the common degenerate case of "losing namespacing scope" or "as bad as having global methods".
Monkeypatch/Extend String
Convenient and very "OO-message-passing" style at the cost of globally affecting all String in your application. That cost can be large because doing so breaks an implicit boundary between Ruby core and your application and it also scatters a component of "your application" in an external place. The functionality will have global scope and at worst will unintentionally interact with other things it shouldn't.
Worthy mention: Ruby has a Refinements feature that allows you to do do "scoped monkeypatching".
Worthy mention 2: Ruby also lets you includes modules into existing classes, like String.class_eval { include MyCustomization } which is slightly better because it's easier to tell a customization has been made and where it was introduced: "foo".method(:custom_method).owner will reveal it. Normal Monkeypatching will make it as if the method was defined on String itself.
Utils Module
Commonly done in all programming languages, a Util module is simply a single namespace where class methods/static methods are dumped. This is always an option to avoid the global pollution, but if Util ends up getting used everywhere anyways and it gets filled to the brim with unrelated methods, then the value of namespacing is lost. Having a method in a Util module tends to signify not enough thought was put into organizing code, since without maintenance, at it's worst, it's not much better than having global methods.
Private Method
Suppose you only need it in one class -- then it's easy to just put it into one private method. What if you need it in many classes? Should you make it a private method in a base class? If the functionality is inherent to the class, something associated with the class's identity, then Yes. Used correctly, the fact that this message exists is made invisible to components outside of that class.
However, this has the same downfall as the Rails Helper module when used incorrectly. If the next added feature requires that functionality, you'll be tempted to add the new feature to the class in order to have access to it. In this way the class's scope grows over time, eventually becoming near-global in your application.
Helper Module
Many Rails devs would suggest to put almost all of these utility methods inside rails Helper modules. Helper modules are kind of in between Utils Module and Private Method options. Helpers are included and have access to private members like Private Methods, and they suggest independence like Utils Modules (but do not guarantee it). Because of these properties, they tend to end up appearing everywhere, losing namespacing, and they end up accessing each other's private members, losing independence. This means it's more powerful, but can easily become much worse than either free-standing class/static methods or private methods.
Create a Class
If all the cases above degenerate into a "global scope", what if we forcibly create a new, smaller scope by way of a new class? The new class's purpose will be only to take data in and transform it on request on the way out. This is the common wisdom of "creating many, small classes", as small classes will have smaller scopes and will be easier to handle.
Unfortunately, taking this strategy too far will result in having too many tiny components, each of which do almost nothing useful by themselves. You avoid the ball of mud, but you end up with a chunky soup where every tiny thing is connected to every other tiny thing. It's just as complicated as having global methods all interconnected with each other, and you're not much better off.
Meta-Option: Refactor
Given the options above all have the same degenerate case, you may think there's no hope and everything will always eventually become horribly global -- Not True! It's important to understand they all degenerate in different ways.
Perhaps functionality 1, 2, 3, 4... 20 as Util methods are a complete mess, but they work cohesively as functionality A.1 ~ A.20 within the single class A. Perhaps class B is a complete mess and works better broken apart into one Util method and two private methods in class C.
Your lofty goal as an engineer will be to organize your application in a configuration that avoids all these degenerate cases for every bit of functionality in the system, making the system as a whole only as complex as necessary.
My advice
I don't have full context of your domain, and you probably won't be able to communicate that easily in a SO question anyways, so I can't be certain what'll work best for you.
However, I'll point out that it's generally easier to combine things than it is to break them apart. I generally advise starting with class/static methods. Put it in Util and move it to a better namespace later (Printer?). Perhaps in the future you'll discover many of these individual methods frequently operate on the same inputs, passing the same data back and forth between them -- this may be a good candidate for a class. This is often easier than starting off with a class or inheriting other class and trying to break functionality apart, later.

How to extend Rails models?

Say, I have a Rails model with a method:
class Order < ApplicationRecord
def process
do_some
do_some_more
do_even_more_here
end
end
Its purpose is solely Rails-model based, meaning its actions are performed on the object itself. What would be the best design pattern to adapt if I'd want to refactor this method and move it out somewhere else?
What I've found so far is that a Decorator shouldn't be the answer as they are more view related. ServiceObject is meant to only perform calculations without the ActiveRecord object and Concerns are mixins that divide responsibilities over several (ActiveRecord) objects.
What I've found so far is that a Decorator shouldn't be the answer as
they are more view related.
Yes, the decorator pattern is most often used in Rails apps to decorate models with view specific behavior. That does not necessarily mean that you can't use the pattern for other purposes.
Rather what you should consider is that models even with no code instead are already fat objects due to the insane amount of features that they get from ActiveModel and ActiveRecord:
validations
persistence
dirty tracking
type casting
querying
etc
A decorator may just add more fat even through the code is neatly tucked away in a separate class.
ServiceObject is meant to only perform calculations without the
ActiveRecord object
Stop listening to whoever told you this. The ServiceObject pattern is really just about creating single purpose objects that do one single job and do it well.
ActiveJob is an example of the ServiceObject pattern. And yes it even has an API for passing in ActiveRecord objects. What you are describing sound like a prime candidate for a ServiceObject or ActiveJob.
Concerns are mixins that divide responsibilities over several
(ActiveRecord) objects.
Mixins don't divide responsibilities. They share behaviors between classes. Its basically like copy-pasting the same methods between a set of classes.
Service object is the one you are looking for.
Mixins and concerns are just a bunches of code you want to mix and share, they can be anywhere.
Make a service object, design it’s public and private interfaces. If you are thinking it’s coming too fat just separate them, easy as that. It might worth reading about SOLID.

Why is mocking with DI better than mocking objects in objective-c?

this blog article says that:
While there are sometimes sensible ways to mock out objects without DI
(typically by mocking out class methods, as seen in the OCMock example
above), it’s often flat out not possible. Even when it is possible,
the complexity of the test setup might outweigh the benefits. If
you’re using dependency injection consistently, you’ll find writing
tests using stubs and mocks will be much easier.
but it doesn't explain why. What are possible scenarios where DI (injecting an id object conforming to protocol) will serve better for mocking in Objective-C, than simple OCMockito:
[given([mockArray objectAtIndex:0]) willReturn:#"first"];
[verifyCount(mockArray, times(1)) objectAtIndex:];
?
I've noticed that it is easier to create a separate class for test target when the original class do some async stuff.
Let assume you write a test for UIViewController which has a LoginSystem dependency which uses AFNetworking to do a request to the API. LoginSystem takes a block argument as a callback. (UIViewController->LoginSystem->AFNetworking).
If you make a mock of LoginSystem probably you will end with problems how to fire a callback block to test your UIViewController behaviour on success/failure. When I tried that I ended with MKTArgumentCaptor to retrieve a block argument and then I had to invoke it inside a test file.
On the other hand, if you create a separate class for LoginSystem (let call it LoginSystemStub which extends from LoginSystem) you are able to "mock" a behaviour in 3 lines of code and outside the test file. We should also keep our test file clean and readable.
Another case is that verify() doesn't work with checking asynchronous behaviour. It is much more easier to call expect(smth2).will.equal(smth)
EDIT:
Pointers to NSError (NSError**) also don't work well with verify() and it's better to create a stub :D
Imagine you are trying to test a more complex behavior of an object interacting with one of its child objects. To make certain that the parent object is operating correctly, you have to mock all the methods of the child object and even potentially track its changing state.
But if you do that, you just wrote an entirely new object in a confusing and convoluted way. It would have been simpler to write an entirely new object and tell the parent to use that.
With DI you inject your model at runtime, it's not bound in your classes but only in the configuration.
When you want to mock you just create a mock model and inject that instead of your real data. Besides the model, you changed your implementation in a single line.
See here for a hands on example or here for the idea behind it.
Disclaimer: Of course you can mock other stuff than the model, but that's probably the most common use-case.
The answer is: It's not better. It's only better if you need some super custom behavior.
The best thing about it is that you don't have to create an interface/protocol for every class you inject and you can limit to DI the modules you really need to inject making your code cleaner and more YAGNI.
It applies to any dynamic language, or language with reflection. Creating so much clutter just for the sake of Unit-Tests struck me as a bad idea.

rails coding conventions to improve performance

In my current project, i notice few thing,
Maximum part of the business logic are moved to helper.
Included all helper files in a module under lib directory and included that module in application controller.
In many methods, no argument passed, instead they used the instance variable(create instance variable in calling method and use that instance variable in the called method).
Each action will call a helper method to execute business logic and that method will call some other helper methods.
All method are written as public, No protected and private method.
Models are used only for validation.
are those points follows good coding conventions? if not, can you suggest me the best coding standard to improve performance?
First, convention has nothing to do per se with performance.
Maximum part of the business logic are moved to helper.
I would say this is very bad. One of the popular idioms is "fat models, skinny controllers", which works most of the time. Put all the business logic you can in your models, where they belong. If you have really complicated views you want to simplify, use decorators (e.g the draper gem), and then separate business logic (model) and view logic (decorators) into their according locations.
Included all helper files in a module under lib directory and included that module in application controller.
Okay I think. As long as you have one place to maintain that chain, it feels okay. If it leads to misunderstandings/misusings/hacking around, then: not okay.
In many methods, no argument passed, instead they used the instance variable
If you're talking about methods in your model: this is good, since the method is targeted at the scope of your instance, and not of your class.
Each action will call a helper method to execute business logic and that method will call some other helper methods.
Sounds strange. The controller is responsible for preparing your data used in the view. If you are preparing specific data in your helpers to assign them to your view for usage, consider putting these into a decorator (as mentioned above). But calling a helper in almost every action sounds like something is done the wrong way.
All method are written as public, No protected and private method.
Non-public methods should not be public. Take a look at helper_method and hide_action from ActionController.
Models are used only for validation.
Wrong. Models contain the business logic, as mentioned above. What about modifying things in the console? Would you want to update all logical related data by hand, then? Do you do this "by hand" in your controller right now (which it seems like) ? What about when you introduce an API, do you copy-paste the code in there to not miss some logic? And what when the logic changes, are you really sure all required endpoints manually and independently handling that logic are also updated?
There's a reason models have relations, callbacks and instance methods. Use them!
Performance is not related to your arguments; they are about project organization.
Maximum part of the business logic are moved to helper
This shouldn't happen, you should move the business (aka models) logic inside the models. Rails doesn't force you doing it, so keeping the logic organization is up to developers.
Models are used only for validation
This is a consequence of putting the business (aka models) logic outside the models. You should move it from the controllers/helpers to the models. Again, Rails doesn't force you to do that, so it's up to developers to do it.
Included all helper files in a module under lib directory and included that module in application controller.
In many methods, no argument passed, instead they used the instance variable(create instance variable in calling method and use that instance variable in the called method).
Each action will call a helper method to execute business logic and that method will call some other helper methods.
All method are written as public, No protected and private method.
I think that these points are (some more, some less) related to the Rails Helper design. One flaw of Rails is the Helper design: they go against the OO pattern and usually end up by being a bunch of unorganized functions, à la PHP.
For this reason some people use Decorators. Decorators "add an OO layer of presentation logic" (from Draper), allowing to organize better the view related methods.
If you want to examine the argument, I suggest you the following links:
Google search about decorators
Draper
The Ruby Toolbox, presenters category

Is it tractable to have Rails models not subclass ActiveRecord or ActiveModel?

I don't like the idea that in Rails models are used both for business logic and persistance. I'd love to separate the two: have my models contain business logic, and use another class hierarchy to persist.
Has anyone tried this and gotten any traction? Off the top of my head it seems like it goes too strongly against Rails: form_for requires an ActiveModel object to work, as do many common plugins that work directly on business objects.
Any thoughts?
I think it's going to be hard/annoying to do it exactly as you state, but there are some good ways to separate out your code.
One way to do it would be to, just as you said, have 2 separate classes, one for persistence and one for business logic. Let's call them Foo and FooBL. Foo would inherit from ActiveRecord, contain validation logic, and some simple methods for querying and manipulating the data. FooBL would be a regular ruby class that would use the Foo class as needed. You could even use some of Ruby's Delegation features so some of the attributes and methods of Foo could be used directly.
Another slightly different way is to use Presenters, like in the Draper gem. Rather than breaking off the business logic from the the persistence logic, it breaks off the view-related logic. Not exactly what you're looking for, but it still helps in cleaning up your code.
I would also recommend that you take a look at Avdi Grimm's book, Object on Rails. He takes a deep look at some of these patterns and practices.
Good luck!

Resources