Astro Lee Astro Lee - 23 days ago 7
Javascript Question

Translating JavaScript into Ruby, for splitting Excel data into two dimensional variables

Below is JavaScript for splitting copy & pasted Excel data. My purpose is to split given Excel data into each unit cell, and reuse them in the HTML side. My problem is that I was able to write it in Javascript, but I'm having trouble rewriting it in Ruby. I need some help here.

Here is my JavaScript:

var data = $('textarea[name=excel_data]').val();
console.log(data);
var rows = data.split("\n");
var l = rows.length - 3;
console.log(l);
var table = $('<table class="table table-bordered" />');
var datas = new Array();
for(var y in rows) {
var cells = rows[y].split("\t");
var row = $('<tr />');
datas[y] = new Array();
for(var x in cells) {
row.append('<td id='+y+x+'>'+cells[x]+'</td>');
datas[y][x] = cells[x];
$('#excel_table_a'+l+'_'+y+x).html(datas[y][x]);
$('#excel_table_b'+l+'_'+y+x).html(datas[y][x]);
$('#excel_table_c'+l+'_'+y+x).html(datas[y][x]);
$('#excel_table_d'+l+'_'+y+x).html(datas[y][x]);
$('#excel_table_e'+l+'_'+y+x).html(datas[y][x]);
$('#excel_table_z'+l+'_'+y+x).html(datas[y][x]);
} //data generate
table.append(row);
}


This is my attempt in Ruby:

data = @bindo.bindo_input
rows = data.split("\n")
length = rows.length - 3
@datas = Array.new
cells = Array.new { }
rows.length.each do |y|
cells << rows[y].split("\t")
@datas[y] = Array.new
cells.length.each do |x|
@datas[y][x] = cells[x]
end
end


When I try to run this code on Rails, I get an error message like this:


undefined method `each' for 7:Fixnum


I would really appreciate you, for any help.

Answer

rows.length returns a number.

each is a method defined on Range, Enumerable, Hash, and Array (and maybe others, but not integer).

What you're trying to do (iterate rows.length times) can be accomplished with any of the following:

# Enumerator#times
rows.length.times do |i|

# Enumerator#times + each
rows.length.times.each do |i|

# Range#each
0.upto(rows.length - 1).each do |i|

# another Range#each
(0..(rows.length - 1)).each do |i|

# Array#each
Array.new(rows.length).each do |i|

Another note about your code: you are using Array.new to build arrays which is fine, though you could simply use [] as well. The brackets in cells = Array.new {} aren't doing anything. It is possible to pass a block to the Array.new constructor, but you don't seem to be using it for the correct purpose. See Ruby array creation, Array.new vs []

Also, doing a little refactor:

rows = @bindo.bindo_input.split("\n")
corrected_rows_length = rows.length - 3

@datas = []
cells = []

corrected_rows_length.times do |y|
  cells << rows[y].split("\t")
  @datas[y] = []
  cells.length.times do |x|
    @datas[y][x] = cells[x]
  end
end
Comments