I'm currently using Capybara / Poltergeist with PhantomJS. Is there any way to get files that were downloaded by the 'browser' using this setup (e.g. that would be obtained after navigating to a URI)?
Either the URI of the file or the actual file itself would be great. Thanks in advance!
One of solution is this - http://it.fyber.com/blog/2012/11/29/capybara-poltergeist-and-csv-downloads/
Other is to use CSV Ruby library.
Download CSV File is here.
id,name,note
1,name1,note1
2,name2,note2
3,name3,note3
And, your spec file
require 'csv'
feature "Products", :type => :feature do
describe "Download CSV" do
# ... click csv download button by Capybara
rows = CSV.parse(page.body, :row_sep => "\r\n", :force_quotes => true)
# [["id", "name", "note"], ["1", "name1", "note1"], ["2", "name2", "note2"], ["3", "name3", "note3"]]
# assert csv header
header = rows[0]
expect(header).to eq ["id", "name", "note"]
# assert csv rows
# it's better to define expected csv rows and use `each` method
expect(rows[1]).to eq ["1", "name1", "note1"]
expect(rows[2]).to eq ["2", "name2", "note2"]
expect(rows[3])>to eq ["3", "name3", "note3"]
end
end
Related
This may have been asked long time ago but I couldn't find a good answer anywhere.
Current situation of my application is:
Rails API (no views)
TypeScript JS
Now, i have been given a task to build a CSV feature...
Question is,
how do i do it in rails api?
how should my frontend handle this?
this is my not working endpoint:
def download_csv
headers = ['column one', 'column two', 'column three']
csv_data = CSV.generate(headers: true) do |csv|
csv << headers
csv << ["A", "B", "C"]
end
csv_data.strip
send_file(
csv_data,
disposition: "attachment; csv-.csv",
)
end
You want to use send_data and not send_file:
def download_csv
# Move the CSV generation out of the the controller
# for example into a service object where it can be tested in isolation
headers = ['column one', 'column two', 'column three']
csv_data = CSV.generate(headers: true) do |csv|
csv << headers
csv << ["A", "B", "C"]
end
send_data(
csv_data,
filename: 'myfile.csv', # suggests a filename for the browser to use.
type: :csv, # specifies a "text/csv" HTTP content type
)
end
To use send_file you would actually need to write the CSV to a file on the servers file system - which might make sense if the CSV generation is expensive.
I am trying to scrape player information from MLS sites to create a map of where the players come from, as well as other information. I am as new to this as it gets.
So far I have used this code:
require 'HTTParty'
require 'Nokogiri'
require 'JSON'
require 'Pry'
require 'csv'
page = HTTParty.get('https://www.atlutd.com/players')
parse_page = Nokogiri::HTML(page)
players_array = []
parse_page.css('.player_list.list-reset').css('.row').css('.player_info').map do |a|
player_info = a.text
players_array.push(player_info)
end
#CSV.open('atlantaplayers.csv', 'w') do |csv|
# csv << players_array
#end
pry.start(binding)
The output of the pry function is:
"Miguel Almirón10\nMidfielder\n-\nAsunción, ParaguayAge:\n23\nHT:\n5' 9\"\nWT:\n140\n"
Which when put into the csv creates this in a single cell:
"Miguel Almirón10
Midfielder
-
Asunción, ParaguayAge:
23
HT:
5' 9""
WT:
140
"
I've looked into things and have determined that it is possible nodes (\n)? that is throwing off the formatting.
My desired outcome here is to figure out how to get the pry output into the array as follows:
Miguel, Almiron, 10, Midfielder, Asuncion, Paraguay, 23, 5'9", 140
Bonus points if you can help with the accent marks on names. Also if there is going to be an issue with height, is there a way to convert it to metric?
Thank you in advance!
I've looked into things and have determined that it is possible nodes (\n)? that is throwing off the formatting.
Yes that's why it's showing in this odd format, you can strip the rendered text to remove extra spaces/lines then your text will show without the \ns
player_info = a.text.strip
[1] pry(main)> "Miguel Almirón10\n".strip
=> "Miguel Almirón10"
This will only remove the \n if you wish to store them in a CSV in this order
Miguel, Almiron, 10, Midfielder, Asuncion, Paraguay, 23, 5'9", 140
then you might want to split by spaces and then create an array for each row so when pushing the line to the CSV file it will look like this:
csv << ["Miguel", "Almiron", 10, "Midfielder", "Asuncion", "Paraguay", 23, "5'9\"", 140]
with the accent marks on names
you can use the transliterate method which will remove accents
[8] pry(main)> ActiveSupport::Inflector.transliterate("Miguel Almirón10")
=> "Miguel Almiron10"
See http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-transliterate and you might want to require 'rails' for this
Here's what I would use, i18n and people gems:
require 'people'
require "i18n"
I18n.available_locales = [:en]
#np = People::NameParser.new
players_array = []
parse_page.css('.player_info').each do |div|
name = #np.parse I18n.transliterate(div.at('.name a').text)
players_array << [
name[:first],
name[:last],
div.at('.jersey').text,
div.at('.position').text,
]
end
# => [["Miguel", "Almiron", "10", "Midfielder"],
# ["Mikey", "Ambrose", "22", "Defender"],
# ["Yamil", "Asad", "11", "Forward"],
# ...
That should get you started.
I'm ruby-newbie and i need to seed my database from YAML. After loading YAML in seeds.rb i got this array of hash :
{"projects"=>[{"title"=>"Family", "todos"=>[{"text"=>"buy a milk", "isCompleted"=>false},
{"text"=>"Change oil in engine", "isCompleted"=>false},
{"text"=>"To send the letter", "isCompleted"=>true},
{"text"=>"To drink smt", "isCompleted"=>false}, {"text"=>"Buy t-shirt", "isCompleted"=>false}]},
{"title"=>"Job", "todos"=>[{"text"=>"Call chief", "isCompleted"=>true},
{"text"=>"To send documents", "isCompleted"=>true},
{"text"=>"Make todolist", "isCompleted"=>false}]},
{"title"=>"Other", "todos"=>[{"text"=>"To call friend", "isCompleted"=>false},
{"text"=>"Prepare for trip", "isCompleted"=>false}]}]}
My code:
seed_file = Rails.root.join('db', 'seeds', 'seeds.yml')
config = HashWithIndifferentAccess.new(YAML::load_file(seed_file))
How i can iterate it and create new Projects and Todos? Please help!
You can do something like this to iterate each of the projects and todos:
Let my_hash be set to that hash you have, then
my_hash[“projects”].each do |project|
# do whatever you need to do with each item in the hash e.g.
puts project[“title”]
# then to get the todos…
project[“todos”].each do |todo|
puts todo[“text”]
end
end
The easiest way to do it is to put your YAML seed files in db/seeds/, then put this in your db/seeds.rb file:
require 'active_record/fixtures'
seeds_dir = File.join(Rails.root, 'db', 'seeds')
seed_files = Dir["#{seeds_dir}/**/*.yml"].map {|f| f[(seeds_dir.size + 1)..-5] }
ActiveRecord::FixtureSet.create_fixtures(seeds_dir, seed_files)
That will load all of your seeds the same way that fixtures are loaded during tests.
Any idea how to write view specs (presence of headers, rows, etc.) for a generated xlsx file from the xlsx gem? Not sure if I'm doing it correctly in the first place but here's what I have so far
RSpec.describe "spreadsheet.xlsx.axlsx", :type => :view do
...
it "should have header Books" do
assign(:spreadsheet, spreadsheet)
render
# rendered.rows[0].cells.map(&:value).should include "Books"
end
end
In pry, rendered is in a utf-8 encoded string I'm not sure how to parse for headers, etc.
=> "PK\u0003\u0004\u0014\u0000\u0000\u0000\b\u0000\u0000\u0000!\xECc8k\xD4\
Is there a way I can just test the generated xlsx file like I would an html view?
Something like...
it "has header Books" do
assign(:worksheet, worksheet)
render
expect(rendered).to have_xpath("(//table)[1]/thead/tr/td", :text => "Books")
end
Thanks in advance!
It appears rendered is the raw response so you can use something like the axlsx_rails request specs:
File.open('/tmp/xlsx_temp.xlsx', 'w') {|f| f.write(rendered) }
wb = nil
expect{ wb = Roo::Excelx.new('/tmp/xlsx_temp.xlsx') }.to_not raise_error
wb.cell(2,1).should == 'Some value'
This uses the roo gem to parse the file since Axlsx does not read xlsx.
See:
https://github.com/straydogstudio/axlsx_rails/blob/master/spec/axlsx_request_spec.rb#L19-L22
Hi i want to read and write data from CSV and excel file both.Can anyone please help me that
which gem or plugin is more suitable for this.
ruby 1.9.x provides a nice and fast CSV class in Stdlib, see http://www.ruby-doc.org/stdlib-1.9.3/libdoc/csv/rdoc/index.html.
For spreadsheets, I'd suggest http://spreadsheet.rubyforge.org/, or as already suggested, https://github.com/hmcgowan/roo
edit
I could dig out an example for csv from my code, this may help you to get started.
import:
CSV.foreach(params[:csv][:csv_file].tempfile) do |row|
# do something with your row ...
end
export:
#export = CSV.generate do |csv|
# adding header columns
csv << [
'Column 1',
'Column 2',
'Column 3' #, ...
]
#records.each do |record|
csv << [
record.name,
record.description,
record.created_at #, ...
]
end
end
# if you want to send the data directly to the client (works inside a controller action)
send_data #export, :type => 'text/csv; charset=utf-8; header=present', :disposition => 'attachment: filename=export.csv'
Can you try roo gem for excel
https://github.com/hmcgowan/roo
And for CSV
https://github.com/arydjmal/to_csv