1

I would like to display data in Columns rather than Rows in my web page.

What is the most efficient way to do this using Ruby on Rails?

Many thanks for your help!

  • 1
    please give some more infos, your code, just anything. you can't answer a question like that. – Beffa Jan 24 '10 at 20:30
  • Sorry, it was a bit tough because I cannot add a picture, or figure out how to format the text to display an example of the layout I am trying to achieve. If I have a index action which returns a set of records in @records, my scaffold layout displays all the fields in a table, with the column names along the top of the table, and the records running down. Instead, I want the column names down the left hand side of the table, and the records in columns across the page. –  Jan 24 '10 at 21:06

4 Answers4

1

Simple solution would be to 'rotate' the information, using an array. Like this (pseudo) code (cannot check if atm)
Controller code:

@stuffs = Stuff.find(:all)
@rotated = []
@rotated[0] = [] # Stuff column0
@rotated[1] = [] # Stuff column1
# etc
index = 0
# Now put the stuff in an array for easy(ier) access
@stuffs.each do |stuff|
  @rotated[0][index] = stuff.detail0
  @rotated[1][index] = stuff.detail1
  index += 1
end

In your View you'd need something like this:

<table>
Table head here!
<% 2.times do |row| %>  # Build table (we have 2 stuff details, hence the 2 here)
  <tr>
  <% index.times do |column| %>
    <td><%= @rotated[row][column] %></td>
  <% end %>
  </tr>
<% end %>
<table>

There are of course better solution, but this seems the most simple/general to me. To rotate some data from some Model.

Like others said with more information we can help you probably much better!

Veger
  • 37,240
  • 11
  • 105
  • 116
  • Hey - this worked really well for me. There was just one small problem - I needed to change index++ to index+=index. Thanks very much. –  Jan 25 '10 at 21:10
0

Here's my solution. It takes an array, say ["a", "b", "c", "d"] and converts it into this array: [["a", "b"], ["c"], ["d"]] which is then easy to use to display data in columns.

def categories_in_columns(categories, number_of_groups=3)
  groups = []
  elements_per_column       = categories.size / number_of_groups
  extra_elements            = categories.size % number_of_groups
  has_extra_elements        = (extra_elements > 0 ? 1 : 0)

  0.upto(number_of_groups-1).each do |i|
    groups[i] = []
    while groups[i].size < (elements_per_column + has_extra_elements)
      groups[i] << categories.shift
      extra_elements -= 1 if groups[i].size > elements_per_column
    end
    has_extra_elements = 0 if extra_elements == 0
    groups[i].compact!
  end
  groups.delete_if { |i| i.empty? }
end

And specs for it:

it "arranges categories into columns" do
  categories_in_columns(["a", "b", "c", "d", "e"]).should == [["a", "b"], ["c", "d"], ["e"]]
  categories_in_columns(["a", "b", "c", "d"]     ).should == [["a", "b"], ["c"], ["d"]]
  categories_in_columns(["a", "b", "c"]          ).should == [["a"], ["b"], ["c"]]
  categories_in_columns(["a", "b"]               ).should == [["a"], ["b"]]
  categories_in_columns(["a"]                    ).should == [["a"]]
end
orion3
  • 9,797
  • 14
  • 67
  • 93
0

Adapted from an earlier, similar question/answer:

def rotate(matrix)
  columns = matrix.first.size
  rows = matrix.size
  result = []
  columns.times { |y|
    result[y] = []
    rows.times { |x|
      result[y][x] = matrix[x][y]
    }
  }
  result
end

I believe this may be called "transposition," since rather than rotating the array, you really just want to make row 1 into column 1 and so forth. That is, if you rotated a quarter-turn counterclockwise, array[0][0] would wind up in the lower left-hand corner. The above implementation assumes you still want [0][0] to remain in the upper left:

1 2 3 4
5 6 7 8
9 0 a b

1 5 9
2 6 0
3 7 a
4 8 b

I'm also assuming all of the rows have the same number of elements/columns.

Oh hey, and wouldn't you know it: Array#transpose...

<%= render :partial => 'mytable', :collection => @array.transpose %> # untested
Community
  • 1
  • 1
Eric
  • 2,539
  • 18
  • 23
  • This approach looks great. It is probably my fault for not being totally clear, but I could not get .first.size to work with my ActiveRecord object This is why I chose the above answer. –  Jan 25 '10 at 21:13
  • 1
    mine was pretty much a helper method, but all in all it winds up being just an implementation of Array#transpose. Guess that part wasn't clear. If you have a two-dimensional array you can just do @array.transpose to get the same result that I illustrated above. – Eric Jan 26 '10 at 00:21
0

If you are pulling the data from a database, you should consider using the PIVOT operator (in SQL Server at least - I'm not sure about SQLLite or MySQL). This way, you could still use "normal" UI methods and still show the data in columns rather than rows. Just a thought...

Mark Brittingham
  • 28,545
  • 12
  • 80
  • 110