2017-03-10 3 views
0

Ich habe eine @commit, die has_many :diffs, so habe ich eine @diffs = @commit.diffs.Wie kann ich diesen geschachtelten Iterator-Check viel trockener und effizienter machen?

Jede diff hat eine .body, die eine Zeichenfolge enthält.

Das Problem, das ich in laufen lasse, ist, dass ich schnell in der Lage sein müssen, die body jeder diff zu überprüfen, dass commit gehört zu sehen, ob es eine Bedingung erfüllt (das heißt nämlich body.include? (line_count - 3).to_s). Wenn ja, möchte ich das diff speichern/verwenden.

So wie ich umgesetzt haben es durch dies zu tun ist:

<% @diffs.each do |diff| %> 
    <% if diff.body.include? (line_count - 3).to_s %> 
     <% diff.body.lines.each do |dl| %> 

     <% end %> 
    <% end %> 
    <% end %> 

Welche unelegant scheint. Wie kann ich das TROCKENER, effizienter und sauberer machen?

Ich möchte auch das aus meiner Sicht nehmen, und in einen Helfer/Dekorateur oder etwas bewegen.

+0

Aufruf 'to_s' auf etwas ziemlich garantiert Ihnen einen String zurück, und eine beliebige Zeichenfolge ist immer logisch wahr. Diese Bedingung wird niemals nicht auslösen. – tadman

Antwort

0

Im Allgemeinen ist es korrekt zu sagen, dass diese Art von Logik nicht in den Ansichten sein sollte. Ich würde empfehlen, einen Dekorateur dafür zu verwenden. Werfen Sie einen Blick auf die Draper Edelstein für die Hilfe mit diesem. Das Folgende ist ein Beispiel dafür, wie Sie dies mit Draper machen können.

# In you controller 
class YourController < ApplicationController 
    # ... 
    @diffs = @commit.diffs.decorate # after adding draper, add `.decorate` to this line in the controller 
    # ... 
end 

# In a Draper decorator 
class DiffDecorator < Draper::CollectionDecorator 
    def get_some_subset_of_the_diffs 
    decorated_collection.select { |diff| diff.body.include? (line_count - 3).to_s } 
    end 
end 

# Your view 
<% @diffs.get_some_subset_of_the_diffs.each do |diff| %> 
    <% diff.body.lines.each do |dl| %> 

    <% end %> 
<% end %> 

Auch, was versuchst du mit diff.body.include? (line_count - 3).to_s zu erreichen? Es gibt Fälle, in denen dies möglicherweise ausgeführt wird, aber dies führt wahrscheinlich nicht die gewünschte Logik. Soll es Diffs mit weniger als 3 geänderten Zeilen erkennen?

+0

Re: Ihre Frage, nein .... diese Logik überprüft den String-Wert des 'diff.body', um zu sehen, ob es den Wert von' line_count - 3' enthält, der eine ganze Zahl zurückgibt, dann muss ich es in konvertieren eine Zeichenkette - was '.to_s' tut. – marcamillion

+0

In diesem Fall können Sie dies mit 'select' erreichen. Meine Antwort wurde aktualisiert, um dies zu berücksichtigen. – Glyoko

0

Warum nicht die Mehrheit dieser Logik in Ihre Modelle übertragen? Angenommen, Sie Commit und Diff Modelle haben, könnten Sie haben:

# NOTE: you'll want to change the name "affected" to something that is more meaningful. I don't quite understand what matching on the line count is meant to do here. 

class Commit 
    def affected_diffs(line_count) 
    # the `@diffs ||=` part is optional memoization (read more here: http://gavinmiller.io/2013/basics-of-ruby-memoization/) 
    # it can be helpful for performance if you call this method multiple times in your view 
    @diffs ||= diffs.select { |diff| diff.affected?(line_count) } 
    end 
end 

class Diff 
    # no need to rewrite this logic if you also choose to use it elsewhere 
    def affected?(line_count) 
    body.include? (line_count - 3).to_s 
    end 
end 

# then in your view 
<% @commit.affected_diffs(line_count).each do |diff| %> 
    <%# work with each diff %> 
<% end %> 
Verwandte Themen