The issue with both each of these posts is that the code will not work
in a lot of situations due to one small hole. I was hoping to do this
entire thing with a DB, I think I may have now found that way to do
this through the post.
In either case, the hole with that particular iterator comes from a
possible lack of efficiency [I don't know ruby that well], and a
situational issue.
def feature_types
results = Hash.new
prev = nil
@features.each do |f|
if (f.feature_type.name != prev)
results[f.feature_type.name] =
end
results[f.feature_type.name] << f
prev = f.feature_type.name
end
results
end
was the code posted above for a loop to solve this issue. the logic
issue lies in
if (f.feature_type.name != prev)
results[f.feature_type.name] =
end
and the using of a "prev" function at all. We can't use a previous
item as a quality method of comparison without retrieving duplicate
results (because your features will potentially [often] have an out-of-
order feature_type list.)
You can't do prev if the feature_type iteration ends up looking like:
[1,2,2,2,1,2]. Both the last 1 and 2 will be included because they
weren't set to be in the prev variable.
The second problem with an iterator like this efficiency. I am not a
Ruby on Rails expert. I do not know if every time you call
f.feature_name.* calls a new query. If it does, that will drop
efficiency on the DB side (calling a potential inf queries as opposed
to just two or three.)
All of that being said, I solved the problem (possibly improperly) by
doing this:
1) Adding a scope definition to feature_types called "with_car", so,
FeatureType.with_car would find me the feature types that, by process,
can exist under the given car. This also uses group to add efficiency
and eliminate duplicates.
2) Iterating through each feature_type and pulling potential features
from the already-established self.features array by using a select to
increase efficiency:
@features = self.features
@feature_types = FeatureType.with_car(self)
@feature_types.each do |feature_type|
feature_type.features = @features.select {|feature|
feature.feature_type_id == feature_type.id}
end
This iterator reduces the DB load down to two queries (although I KNOW
this could be reduced using a long, handwritten Join -- or the
nested_has_many plugin)
The potential for duplicate feature_types is removed in the
FeatureType.with_car scope.
If anyone has a solution and can help me do this more the 'rails way,'
that would be excellent. I greatly appreciate the help and wealth of
knowledge already displayed here.