Is this your first visit? You may want to subscribe to the feed.

Articles tagged with core_ext

Splitting Hairs and Arrays

Am I just dumb, or is it really a lot harder than it should be to break an array up into a set number of chunks?

For example, I have a list of 8 items that I want to break into 3 arrays, each displayed in their own unordered list, like this:

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5
  • Item 6
  • Item 7
  • Item 8

Brian and I spent a ridiculous amount of time (20 minutes, at least) trying to come up with a clean solution to this seemingly simple problem. The closest thing there is to a solution is Enumerable#each_slice in Ruby core or Array#in_groups_of in Active Support.

<% my_array.each_slice((my_array.size.to_f / 3).ceil) do |list| %>
  <ul>
    <% list.each do |item| %>
      <li><%= item %></li>
    <% end %>
  </ul>
<% end %>

or

<% my_array.in_groups_of((my_array.size.to_f / 3).ceil, false) do |list| %>
  <ul>
    <% list.each do |item| %>
      <li><%= item %></li>
    <% end %>
  </ul>
<% end %>

There’s not really a difference between either solution. Both requires that we calculate how many items we want in each list. (We convert the size to a float, divide by the number of columns, then round up. This gives us the same number of items in each column, with the last column having fewer.)

Our solution

We didn’t like having that much logic in the view, so we added a method to enumerable; we thought the division (/) method seemed appropriate since we’re dividing the array into equal parts.

module Enumerable
  # Divide into groups
  def /(num)
    returning [] do |result|
      each_slice((size.to_f / num).ceil) {|a| result << a }
    end
  end
end

Note: this method is now in our awesomeness plugin.

So now we can just divide our array into chunks in the view.

<% (my_array / 3).each do |list| %>
  <ul>
    <% list.each do |item| %>
      <li><%= item %></li>
    <% end %>
  </ul>
<% end %>

Are we dumb? Is there already a way to do this that wasn’t obvious to us and we just wasted our time (and I wasted even more time blogging about it)?

Update: Thanks to Aaron Pfeifer for pointing out the discussion on Jay Field’s blog about something similar. I’ve refactored this code in awesomeness to be more “robust’ (read: convoluted).

Code: core_ext Jun 19, 2008 ● updated Oct 14, 2008 7 comments

Getting a glimpse into Net::HTTP requests

While trying to debug some HTTP code, I wanted to be able to see what the actual HTTP request looked before it was sent. So, I added a #to_s method:

require 'stringio'

class Net::HTTPGenericRequest
  def to_s
    io = StringIO.new
    exec(io, '1.1', path)
    io.string
  end
end

All the built in requests extend HTTPGenericRequest, so now I can call #to_s on any request:

request = request = Net::HTTP::Get.new('/some/path')
request.set_content_type 'text/html'
request.basic_auth 'username', 'password'

puts request.to_s

Which gives me:

GET /some/path HTTP/1.1
Accept: */*
Content-Type: text/html
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

I had also intended to add a #to_s method to the response, but it wasn’t obvious how to accomplish that, and I found my bug before I needed it. So, if anyone feels ambitious…

Code: core_ext Feb 16, 2008 ● updated Oct 14, 2008 1 comment

Round floats to the nearest X

For those pesky times when whole numbers just won’t cut it, but you only want some precision.

7.7.round(0.5)   #=> 7.5
7.95.round(0.5)  #=> 8
8.2.round(1.5)   #=> 7.5
8.3.round(1.5)   #=> 9

The magic, courtesy of Daniel Morrison:

class Float
  def round(round_to = 1.0)
    mod = self % round_to
    rounded = self - mod + (mod >= round_to/2.0 ? round_to : 0)
    rounded % 1 == 0 ? rounded.to_i : rounded
  end
end

Note that do to some quirks with Ruby’s handling of floats, you won’t get what you expect in some situations:

3.5.round(0.2)   #=> 3.4, instead of 3.6
Code: core_ext Jul 18, 2007 4 comments

Subscribe

Browse by Tag