Question

I have the following method:

Now sometimes I want the limit attribute to be ignored

Therefore the .take method would be ignored, at the moment I do not know how to do this gracefully. As setting to nil errors the code.

Any help appreciated - new to ruby.

def articlesByCategory( category, extensions = [ "md" ], limit = 3 )

    # Check category is an array
    if !category.kind_of?(Array)
        category = [ category ]
    end

    # Create Return Array
    ret = []

    # Get the resources that are
    sitemap.resources.select { |r| ( category & Array( r.data.category ) ).present? }.take( limit ).each do |a|

        ret << a

    end

    # Return
    ret

end
Was it helpful?

Solution

First, your code can be significantly refactored to do the same thing it’s doing now. There’s no need to do an each to build an exact copy of the array, and we can apply Kernel#Array to category the same way your did to r.data.category. Finally, any? reads a bit better (IMO) than present?, especially since the value cannot be nil (only caveat is if nil or false is a valid category).

def articles_by_category category, limit = 3
  category = Array(category)
  sitemap.resources.select do |resource|
    (Array(resource.data.category) & category).any?
  end.take(limit)
end

We can easily pull the take out into a conditional to get what you want:

def articles_by_category category, limit = 3
  category = Array(category)
  articles = sitemap.resources.select do |resource|
    (Array(resource.data.category) & category).any?
  end
  limit ? articles.take(limit) : articles
end

It might, however, make sense to just get rid of the limit entirely within the method and impose it externally. This is much more functional and keeps your method from doing a lot of things (what does a limit have to do with getting articles by category? (this method doesn’t even get articles by category, it gets whatever resources is (presumably articles…) for a given category)).

def articles_by_category category
  category = Array(category)
  sitemap.resources.select do |resource|
    (Array(resource.data.category) & category).any?
  end
end

articles_by_category('My Category').take(3)

Note that if category will never be an array (which seems likely given its singular name) than you can further simplify your method to:

def articles_by_category category
  sitemap.resources.select do |resource|
    resource.data.category == category
  end
end

(And of course add the limit feature back in if so desired.)

OTHER TIPS

You could simply do

category ||= []

Did it like this in the end

def articlesByCategory( category, extensions = [ "md" ], limit = 3 )

    # Check category is an array
    if !category.kind_of?(Array)
        category = [ category ]
    end

    # Create Return Array
    ret = []

    # Get Resources
    resources = sitemap.resources.select { |r| ( category & Array( r.data.category ) ).present? }

    # Check limit is set
    if !limit.nil?
        resources = resources.take( limit )
    end

    # Get the resources that are
    resources.each do |a|

        ret << a

    end

    # Return
    ret

end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top