Passing only two variables between controller and view - best practice? - ruby-on-rails

Found this Best Practice and it's even got inspection in RubyMine:
"Only one or two instance variables are shared between each controller and view.)"
(Ruby on Rails Code Quality Checklist)
What is the suggested way for example - to pass two arrays and their total values calculated in the controller, which makes 4 instance variables? Or to pass to a Javascript data table the: data, total items, total items displayed?

I think the most sensible way to respect this is to go from many simple objects to few complex objects.
Let's say, for instance, you have three separate variables now:
data array
total data items
total items displayed
Now, instead of using 3 separate instance variables (one Array, two Fixnum), you could create a Hash which holds all three of them, or perhaps define a new class which responds to methods such as total_items that you can call in the view.
In fact, as one example, will_paginate does something like this: A paginated collection of items is not simply represented as an array, but as a WillPaginate::Collection object, which responds to methods such as current_page, total_pages, total_entries, etc. This is more natural than having separate variables, since it more accurately maps the relationship between the information you're interested in sharing with your view.
As a rule of thumb, I would suggest that anything which corresponds to closely related information should always be in one instance variable, but anything that isn't really related at all should not be "forced" into one variable because of these best practices. Every rule has an exception, so if, for example, you really have 5 different components in your view which have absolutely nothing to do with each other (which is rare), blindly following the best practice might not be the best idea.
Bottom line: Understand the idea behind these rules, and you'll know what to do.

Related

VIPER - Should the Interactor return only the necessary information?

In the VIPER design pattern, should the Interactor return all the information that might be used by multiple presenter actions or should I have a separate struct for each one?
In my case, I have a map that displays places. To display those places I need to retrieve a list of PlaceItem's from a PlacesInteractor which could have only a coordinate and a color (used to change the pin's head color) that would be transformed into a annotations by the presenter.
Now lets say that when the user selects one of the annotations in the map, a callout bubble should be displayed with more details like the place's name and a circle with the color.
Now I should create a RetrievePlaceCalloutInteractor that would return only the information for one place instead of a list of information for multiple places (Right? Or should I have only one Interactor for both scenarios?).
Should this RetrievePlaceCalloutInteractor return a PlaceCalloutItem with only the name and the color (no coordinate) of the place or should I have a single PlaceItem with coordinate, color and name, that would be returned by the RetrievePlaceCalloutInteractor and by the PlaceInteractor, and would be used by the presenter to construct either a CalloutStruct or a list of MKAnnotations?
Thank you.
VIPER is a pattern, not a very formal pattern, not a religion or a complete app architecture. For me VIPER helped to think more about a cleaner architecture but on the way I had to make decisions that were better for my specific scenario without caring to much about VIPER but about clean architecture. So, from my experience and my point of view the answer to your question is 'depends'.
In my case most of the 'Items' (I call them DO from Display Object or Data Object) have almost a one to one relationship with the 'Entities' (I call them MO from Model Object). Most of the interactors manipulate one type of Entity and they have one MO-DO mapper. I usually use the same DO for different use cases if the interactor handle more than one use case.
BUT
I also have some modules using different DOs for different uses cases, although they relate to the same entity, and also I have some DOs with combine the information of several Entities, let's say for example I needed the user name to add it to 'edited by' of a blog post I use the same DO to combine Post and User Entities.
I think VIPER 'wants' one interactor per module, that kind of forces you to have multiple use cases (related) in it, but it is up to you if you want to use different Items (my DOs) or only one.
Being a purist of clean architecture you should have different interactors, different requests and different responses for each use case.
So, as I started, it depends, the important thing is to 'draw' the boundaries properly and it doesn't matter if it's one or ten Items you use for that.

Querying two tables based on the results of one table - Zend 2

I am using TableGateways along with the Object Mapper which uses the exchangeArray() method for getting database results. This method is fine for getting data in one go.
However, I am struggling to render a table of results where I want to get another resultset in the foreach loop for each row by performing a query.
In regular PHP, I would simply write a loop for the first set of data then write another loop within the first loop that would execute a query for each record. This does not follow Zend's MVC approach so how would I achieve the same thing?
This isn't anything to do with joins.
I have a table of invoices and payments. I am outputting a table of payments and for each payment, I want to output the invoices that are tied to that specific payment. I am trying to achieve this using Zend's MVC and TableGateway patterns.
Thanks.
In regular PHP, I would simply write a loop for the first set of data then write another loop within the first loop that would execute a query for each record. This does not follow Zend's MVC approach so how would I achieve the same thing?
Well, the thing is that the MVC pattern is going to add a level of complexity to something like this and that is not necessarily a bad thing.
You can still do the same as you did before, loop through the results & fetch the associated data. However, instead of doing it as you're displaying the data, you would do it in the controller or preferably in a service or DataMapper object. This is the added level of complexity since you'll have to loop through the results twice. Once to gather the associated data & once to display it. Again, this is not necessarily a bad thing since it makes your code more maintainable by not allowing you to change what the data looks like without needing to change how it's gather or vice versa.
Alternatively you could use an ORM such as Doctrine to give you the relationship mapping in one function call (under the hood it's doing essentially the same two loops). Of course, this means you will need to learn how the ORM works and its API.

How best to do a codebase-wide find only on *displayed* instances of a string in Rails?

In several places in a rather complex Rails app there are references to a particular kind of object; let's call them "apples". I'd like to change all of these user-facing references from "apples" to "oranges". This would be simple enough, except that I'd like to retain Apple as class, so I don't want to touch the myriad methods, variables, symbols, etc. that use the word "apple".
There are several orders of magnitude more instances of apple in the code proper than there are user-facing instances of "apple". My question is: How can I zero in on the relatively few displayed instances? Is there a way to perform a search on all and only what is displayed by a browser?
Unless you've taken a disciplined approach to separate your language from your code, such as using localization files, then no, there's no easy way to find instances of displayed text. How is a search supposed to differentiate between 'apple' used as a type column and 'apple' inserted into a page?
This is why you might want to take an approach where you don't embed language in your controllers and models. Instead you could create a helper method to describe them for you:
You have <%= pluralize_model(#apple, 10) %> left.
That method, if constructed properly, would render '10 apples' or whatever term you'd like to use for that type of object.

DB-agnostic Calculations : Is it good to store calculation results ? If yes, what's the better way to do this?

I want to perform some simple calculations while staying database-agnostic in my rails app.
I have three models:
.---------------. .--------------. .---------------.
| ImpactSummary |<------| ImpactReport |<----------| ImpactAuction |
`---------------'1 *`--------------'1 *`---------------'
Basicly:
ImpactAuction holds data about... auctions (prices, quantities and such).
ImpactReport holds monthly reports that have many auctions as well as other attributes ; it also shows some calculation results based on the auctions.
ImpactSummary holds a collection of reports as well as some information about a specific year, and also shows calculation results based on the two other models.
What i intend to do is to store the results of these really simple calculations (just means, sums, and the like) in the relevant tables, so that reading these would be fast, and in a way that i can easilly perform queries on the calculation results.
is it good practice to store calculation results ? I'm pretty sure that's not a very good thing, but is it acceptable ?
is it useful, or should i not bother and perform the calculations on-the-fly?
if it is good practice and useful, what's the better way to achieve what i want ?
Thats the tricky part.At first, i implemented a simple chain of callbacks that would update the calculation fields of the parent model upon save (that is, when an auction is created or updated, it marks some_attribute_will_change! on its report and saves it, which triggers its own callbacks, and so on).
This approach fits well when creating / updating a single record, but if i want to work on several records, it will trigger the calculations on the whole chain for each record... So i suddenly find myself forced to put a condition on the callbacks... depending on if i have one or many records, which i can't figure out how (using a class method that could be called on a relation? using an instance attribute #skip_calculations on each record? just using an outdated field to mark the parent records for later calculation ?).
Any advice is welcome.
Bonus question: Would it be considered DB agnostic if i implement this with DB views ?
As usual, it depends. If you can perform the calculations in the database, either using a view or using #find_by_sql, I would do so. You'll save yourself a lot of trouble: you have to keep your summaries up to date when you change values. You've already met the problem when updating multiple rows. Having a view, or a query that implements the view stored as text in ImpactReport, will allow you to always have fresh data.
The answer? Benchmark, benchmark, benchmark ;)

Transforming objects to other types

I'm working on a RoR app, but this is a general question of strategy for OOP. Consider the case where there are multiple types of references that you are storing data for: Books, Articles, Presentations, Book Chapters, etc. Each type of reference is part of a hierarchy where common behaviors sit at the most general point of inheritance, and at the DB level I am using single-table inheritance. The type is set by use of a select option, so lets say that I was entering the data as if it were a Book, but then realize that it is only a chapter. So I change the type of reference by selecting "Book Chapter", which then posts an update to the existing model/form. The question is what is the correct strategy for handling this?
On one hand it seems preferable to transform the existing record in the DB to avoid id exhaustion, and potentially save on operations for creating/deleting records. This however tends to make the update strategy complex.
On the other hand, it seems more in keeping with general object orientation to create a new object (and record) using the old object to initialize values that you want to persist, then delete the old object. This I think makes more sense in terms of an Object Space (heap), and I think is more aligned to ideas like those of general systems.
However, I haven't nailed this down, and after sitting on it for a while, I'm pitching it to this community to see what "right" way to do this is.
Prefer immutable objects, in other words: the second strategy. Your objects may not be immutable by themselves, but reducing mutability is often a step in the right direction.
Besides that, this is the more natural way. In general OOP terms there's no way to change the type of an object. In your situation you can, but it's still an awkward and unusual thing to do.
On the other hand, if your objects are represented by the same (identical) class and changing the type is done by setting a high-level property, one could argue that re-creating the object is overkill.
Still, reducing mutability is a good think, but if your class is already designed to be mutable, it might not be worth it. (In that special case where there's actually only one actual class from the language point of view)
The transformation you're talking about doesn't seem to warrant a new record or even a new object.
Each of the entries you cited have the same form. They are block of text with siblings, parents and children. A chapter may have a block of text, with a parent book and a child endnote, for example. They are differentiated on a DB level only by their type, which itself could be a field.
All you need is a model to handle these 'elements' differently depending on whether or not it is flagged as a book, or a chapter, etc. If an element is flagged as a chapter, yet has no parent, for example, then you might flag it as a 'book' when it is saved to the DB.
Changing the way an element is flagged doesn't change the element, it only changes the way it is viewed. So long as the element knows how to find it's children the data will compute in the same way. As far as the model is concerned it's just an element you're worrying about. The rest is done in the UI.

Resources