Proper organization of server side code? - ruby-on-rails

I'm relatively new to rails, but I've made a few basic CRUD apps. However, this time, I'm making something different, and I'm not sure how to organize it.
It's essentially a one page app. The user fills out a form, and the code does some calculations based on those values. I have all the code written, but it's all just sitting in the controller. I'm assuming that this isn't correct.
There are two parts:
Using an external API, 2 constant arrays are generated. I need these variables to be global, or at least accessible for the calculator function.
I have a function that takes some inputs from the form that also calls other functions. A simplified version is below. I could put all the code into one function if that's necessary. I have them separate just so that the code is more readable.
def calc(input)
func1(input)
func2(input)
# do more stuff
return answer #I need to show this in the view
end
def func1(a)
end
def func2(b)
end
So, where should I put each part of this code?

To make your controllers thin, you can keep business logic at Service Objects.
Just create "services" directory at "app", add there some class like "user_searcher.rb".
And call it in the controller, passing all necessary data.
Such technique will help you to isolate business logic and incapsulate it in separate class.
BTW read this article http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

I think, from what I understand of you question, is this code should be placed in the helper classes. If you have dedicated class for this calculation, you can use class attributes to access array to access anywhere in the class or declare them constant, in case they are constant.
I don't think making global is a good practice, just because this is needed in some other function, instead return that variable and pass them as parameter where they are needed.

Related

Does this method that changes an instance variable belong in my Rails controller or model?

I have a basic "best practice" question about controllers and instance variables.
Say you have an instance variable in anew or update action in a controller, is it ok to modify that instance variable via a private method in the controller? Or should the method exist in the model?
e.g. in this example below, I need to loop through the attributes of an instance variable, and add or remove something. For example, if I am using nested attributes 3 layers deep and have to remove certain attributes, change them and then add them back in. I know this may seem strange, but assume it is necessary.
def new
#some_thing = SomeThing.new(:some_params)
do_something_to_inst_var # method call
#some_thing.save
end
private
def do_something_to_inst_var
#some_thing.addresses.each do |address|
# modify it in some way
end
end
Or is this bad practice? Should this be a method in the model and should be called like:
#some_thing.do_something_to_inst_var
OR
should we explicitly pass the instance variable to the method like:
def new
#some_thing = SomeThing.new(:some_params)
do_something_to_inst_var(#some_thing) # method call
#some_thing.save
end
private
def do_something_to_inst_var(some_thing)
some_thing.addresses.each do |addresses|
# modify it in some way
end
end
I'm looking for some clarity here, with an example if possible. I'm still learning and trying to improve and I didn't find an answer by searching.
Rails applications should have "thin controllers" and "fat models" for a couple of reasons:
Each object should handle only its own responsibilities. A controller should just be about connecting the web, the the model and the view, which thanks to Rails doesn't take much code. If a controller method refers repeatedly to methods of the same model, it's incorrectly taking on model responsibilities; we say that it's not cohesive or that it has "Feature Envy". It is more likely that if the model changes the controller will have to change in parallel.
It's easier to test models than to test controllers.
Fix it by writing a method in the model that does the model-specific work and call it in the controller (your second option). (Eventually your model will get too fat and you'll have to break it up too, but that's another story.) For example:
class SomeThingsController
def new
#some_thing = SomeThing.new(:some_params)
#some_thing.do_something # method call
#some_thing.save
end
end
class SomeThing
def do_something
addresses.each do |address|
# modify it in some way
end
end
end
Regarding instance variables.
Define them only if necessary. Presumably the one in your example is needed for the view.
Assuming an instance variable is justified at all, there's no reason not to refer to it in private methods of the class that contains it. That's what they're for. So your first option (referring directly to the instance variable) is a bit better than your third option (passing it in). But, as discussed above, extracting a model method is better than both of the other two options.
In my opinion Modifying #instance_vars from private method is okay if your controller is just 100 lines long.
Imagine a scenario where there are 500 LOC in your controller and after a struggle of a couple of hours you found out that the #intance_var is being modified by some private method.
Helpful tips:
create small private methods with single responsibility
put ! at the end of method_name! indicating that it modifies something. Specially this is helpful when you see my_private_method!, ! makes you realize that its modifying something.
lets not put code in controller that do not belong here.
There is one more option:
In Controller:
def new
#some_thing = SomeThing.new(:some_params)
#some_thing_modified = #some_thing.modify_somehow(params)
#some_thing_modified.save
end
In SomeThing Model:
def modify_somehow(params)
result = self.clone
# ... modify result ...
return result
end
Because modify_somehow is now pure function (assuming you don't do anything in ... modify result ... part, that makes it impure), what you gain here is Referential transparency. Main benefit of referential transparency is that you can determine what function/method invocation will do, only by looking at its arguments, and get result of its work only via return value, and not via side effects. This makes your code more predictable, which in turn makes it easier to understand and debug.
There are of course disadvantages: Because you create new object this option can be less performant, it's also more verbose than its alternatives.
Functional programming concepts, like referential transparency, are not very popular in Rails community (probably because of how OO-centric Ruby is). But referential transparency is there if you want it, with its pros and cons.

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

Rails: what are the main reasons for making methods private?

If the end_user cannot access the source code of the app, why we still need to make some methods private?
I'm reading the Pragmatic Agile Web Development with Rails and I couldn't understand why we need to make the following method private (even after reading the explanation):
private
def current_cart Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
cart = Cart.create
session[:cart_id] = cart.id
cart
end
end
It says that it will never allow Rails to make it available as an action, but as a coder, why would I ever do that myself?
As you say there may be no external reason to make it private. However, it also prevents you — or somebody else using your code — from accidentally making use of the method where you're not supposed to.
See it as a sanity check on your own future behaviour if you will.
It aims to encourage good practices and good code.
The idea is that you have two separate parts to your code:
"Above the line" (Public). This is the interface to the rest of the world. This is the API, where calls are made when using instances of the object. Once created, you know that THIS is the area where changes can affect current usages of the code.
"Below the line (Private). This is where detailed logic resides. This code can be changed and refactored freely without any affect to the public interface.
It may help guide your test writing
Private methods may or may not be (unit) tested.
Public methods are more encouraging of both unit and integrated tests as the fact that is is public means that it is serving as the public face for that code and as it is public it might be called from any other point in the future, so having good tests to make sure it continues to work as advertised is essential.
It may help with security as you have greater control who calls private methods (i.e. only public methods in the same class calling them).
It may help reduce name collisions as you have less names in the public space.
End user might not be able to access your code but someone else in your team can definitely access it and they might change it.
The other benefit of encapsulation is that it allows one class ("server") to make a contract with another class ("client") to provide some service with only a very few things being required to be known about the "server" class such as method signature and return type. The benefit is only realized if the contract of what is required and what is returned remains the same. So, in your example, there is no benefit since the contract was broken by Class A.
Instead of class A changing int type to float, class A should create another new variable of type float for other classes to use so that class B is not "broken" or that contract is not broken between them. Class C could refer to new float variable and Class B could still refer to old int variable and everyone is happy. Better yet, methods would used to retrieve values such as: "getUsersAddress" and "getUSersPhoneNumber" depending on what was wanted.
The real benefit of good encapsulation is that Class A can be completely re-written from top to bottom and as long as the contract is honored as to what Class A is expected to do(have methods "getUsersAddress" and "getUSersPhoneNumber"), then everything in Class B and C works the same. Think carefully about what is exposed and how it is exposed. Things that will change often and break other classes need to be considered carefully before exposing. Good encapsulation means hiding things that are expected to change often so to avoid breaking other classes.
It says that it will never allow Rails to make it available as an action,
Hmm, is this in a Rails Conroller class? And is the book you are working through written for Rails 2.x?
In Rails 2.x, by default any public method in a Controller can be triggered by someone accessing the url /name_of_controller/name_of_method .
But there are some methods in your controller that you don't want anyone on the web to trigger, they weren't intended as 'action methods'. So in Rails 2.x, you mark those as protected or private, something not public. "action method" means a method you intend to be directly triggered via a URL.
In Rails 3.x, routing has generally changed such that only certain methods you explicitly route to are available to be triggered via a URL. However, it might still make sense to mark non-action-methods in a Controller as protected or private so:
It's more clear from skimming the source which methods are action methods and which aren't
As a precaution in case someone changes the routing in such a way that would allow a URL to trigger those methods not intended as action methods
Or for general reasons of code organization that other answers mention, that are not specific to Rails controller classes.
There are several reasons as mentioned above. The interesting thing about this encapsulation in ruby is that it can be violated.
See the "send" method and its brother "public_send".
And for a very common metaprogramming technique that uses this method see:
dynamic finders

Where to put complex display logic for a Rails Model?

I have a Location#description method that returns a (really) long string. This string is a human readable description and it's generated according to the values of the Location attributes. However, this code is long and complex, and puts a lot of "not-business" logic in my model.
What is best to do? Bunch all this logic in helpers or create a LocationPresenter class? If I create the presenter, what are some guidelines about doing so? Should I initialize it with a Location or is it okay to use the attribues hash?
Consider refactoring it into a module and include it into the respective model - that's if it has any business logic components. Also look into helper_methods (which work at both the controller and view layers), if not presentation only macros can be added as helpers.
That fact that you've called it 'complex' and realised it need to move out of your model makes me wonder if it could do with some refactoring more inline with Rail's MVC paradigm.

Rails- Using a set of functions across the view , controller and model

i have a function that converts an array to a hash which i would like to use across all the model, controller and view files in the rails app.
Does this violate some core design principle, or am i missing something really obvious?
UPDATE: This is actually a software engineering question. I want to understand why some "convenient" things are not allowed in rails, and i suspect it is precisely because they do not want us to do it
This is likely actually a bad practice. It'd likely be better to instead always work with arrays and hashes in your controllers and models and if necessary convert them in the view to the alternative.
That is, if the data is natively represented as a array throughout your application work with it that way and if required to be a hash in the view either convert it first and assign it or convert it in the view using a helper.
View global helpers go in: helpers/application_helper.rb
If you must call a helper from a controller you can still define it there and I believe you can do:
def Something
....
hashData = #template.helper(arrayData)
end
Calling helpers in a model is REALLY not a good idea, there's no point.
As a final note, encapsulating this logic in a library would likely be ideal, your controllers can call a library & your view helpers can as well.
I think you are: views should not need that method. The controller ought to do it and pass it along to the view for display. The controller or, better yet, service layer might apply that method to a model object, but there's little reason for a model object to know about it.

Resources