Resque require 'csv' not working - ruby-on-rails

I am using resque to process a file in the background. It's a CSV file however I get the following error: uninitialized constant ImportFileHelper::CSV
I have tried to require 'csv' and also include CSV neither will work.
require 'csv'
module ImportFileHelper
HOST = ""
USER_NAME = ""
PASSWORD = ""
def self.process_file(file_data, file_name)
init
#file_name = file_name
begin
csv = CSV.parse(file_data, :headers => true)
csv.each do |row|
#first_name = row["FirstName"]
#last_name = row["LastName"]
#email = row["Email"]
#password = "ch#ngeM3!"
#user_group_name = row["GroupName"].split(",")
#store_name = row["StoreName"]
#external_id = row["ExternalID"]
add_user unless #first_name.nil? || #last_name.nil? || #email.nil? || #password.nil? || #first_name.empty? || #last_name.empty? || #email.empty?
end
rescue NoMethodError => no_method_error
log_error_to_db no_method_error
rescue IOError => error
log_error_to_db error
#errors << error.to_s
rescue Exception => ex
log_error_to_db ex
end
prep_soap_responses_for_output
end
def self.init
HTTPI.log = false
#body = { username: USER_NAME, password: PASSWORD }
#errors = []
#existing_users = []
configure_savon
get_all_groups
get_all_stores
end
def self.prep_soap_responses_for_output
[#existing_users, #errors]
end
def self.log_error_to_db(error)
error.backtrace ||= "Not Available"
if error.message.length > 250
error_message = "There was an error"
else
error_message = error.message
end
ErrorLog.create(message: error_message, trace: error.backtrace, file_name: #file_name)
end
def self.get_store_id
#store_id = #stores[#store_name.to_sym]
end
def self.get_all_stores
#stores = { }
client = Savon::Client.new(HOST + "Storews.asmx?wsdl")
body_data = { mall_id: 1, is_return_offline_store: :false }
#body.merge! body_data
begin
response = client.request :get_store_list, body: #body
if response
hash_response = response.to_hash
stores = hash_response[:get_store_list_response][:get_store_list_result][:store]
stores.each do |s|
store = { s[:name].to_sym => s[:store_id] }
#stores.merge! store
end
end
rescue Savon::Error => ex
log_error_to_db error
#errors << error.to_s
end
end
def self.create_adbuilder_user_object
AdbuilderUser.new(#first_name, #last_name, #email, #user_id, #store_id, #store_name, #user_group_name, #group_id, #external_id)
end
def self.configure_savon
Savon.configure do |configure|
configure.log = false
end
end
def self.add_user
body_data = { first_name: #first_name, last_name: #last_name, user_password: #password, email: #email, external_id: #external_id }
#body.merge! body_data
begin
client = Savon::Client.new(HOST + "UserWS.asmx?wsdl")
response = client.request :add_user, body: #body
if response
#user_id = response.body[:add_user_response][:add_user_result]
if #user_group_name
get_group_id
end
if #store_name
#store_id = get_store_id
unless #store_id.to_s =~ /^0$/
adbuilder_user = create_adbuilder_user_object
UserMailer.create_password(adbuilder_user).deliver if adbuilder_user
end
end
end
rescue Savon::Error => error
log_error_to_db error
if error.message == "(soap:Client) 3: A user with the same email login already exists. Please choose a different login."
#existing_users << #email
else
#errors << error.to_s
end
rescue Exception => error
log_error_to_db error
#errors << error.message.to_s
end
end
def self.get_group_id
begin
#user_group_name.each do |group_name|
user_group_id = #groups_info[group_name.downcase.to_sym]
add_user_to_group user_group_id if user_group_id
end
rescue Exception => error
log_error_to_db error
#errors << error.message.to_s
end
end
def self.get_all_groups
#groups_info = {}
begin
client = Savon::Client.new(HOST + "Usergroupws.asmx?wsdl")
response = client.request :get_user_group_list, body: #body
if response
group = response.to_hash
groups = group[:get_user_group_list_response][:get_user_group_list_result][:user_group]
groups.each do |g|
new_hash = { g[:name].gsub(/\s/, "_").downcase.to_sym => g[:user_group_id] }
#groups_info.merge! new_hash
end
end
rescue Savon::Error => error
log_error_to_db
#errors << error.to_s
end
end
def self.add_user_to_group(group_id)
body_data = { user_id: #user_id, user_group_id: group_id }
#body.merge! body_data
begin
client = Savon::Client.new(HOST + "Usergroupws.asmx?wsdl")
response = client.request :add_user_to_group, body: #body
rescue Savon::Error => error
log_error_to_db error
#errors << error.to_s
end
end
end
So as a work around for this I am doing the csv parsing in the resque job file. This is now allowing it to run. Not sure if this is the best way to do it though.
class ProcessFile
#queue = :rts_file_parser
def self.perform(file_data, file_name)
csv = CSV.parse(file_data, :headers => true)
csv.each do |row|
row_data = { first_name: row["FirstName"], last_name: row["LastName"], email: row["Email"], password: "ch#ngeM3!", user_group_name: row["GroupName"].split(","), store_name: row["StoreName"], external_id: row["ExternalID"] }
ImportFileHelper.process_file file_name, row_data
end
end
end

Mind if I claim the answer (via my comment)?
It looks like it might be a scope resolution issue.
Try ::CSV instead of CSV.

Try adding the gem to the gemfile.

Related

web scraping with rails, getting a big object instead of one for each product

so im trying to do web scraping with rails and kimurai, the problem i ran in to was that for some reason i get a single big object instead of one for each of the products im scraping, here is my code:
class ProductsSpider < Kimurai::Base
#name = "products_spider"
#engine = :mechanize
def self.process(url)
#start_urls = [url]
self.crawl!
end
def parse(response, url:, data: {})
response.xpath("//div[#class='andes-card andes-card--flat andes-card--default ui-search-result ui-search-result--core andes-card--padding-default andes-card--animated']").each do |product|
item = {}
item[:product_name] = product.xpath("//h2[#class='ui-search-item__title ui-search-item__group__element']")&.text&.squish
item[:price] = product.xpath("//span[#class='price-tag-fraction']")&.text&.squish&.delete('^0-9')to_i
item[:shipping] = product.xpath("//p[#class='ui-search-item__shipping ui-search-item__shipping--free']")&.text&.squish
Product.where(item).first_or_create
end
end
end
and here is the function on the controller:
def scrape
url = "https://computacion.mercadolibre.com.ar/componentes-pc-placas-video/msi/cordoba/placa-de-video_NoIndex_True#applied_filter_id%3Dstate%26applied_filter_name%3DUbicaci%C3%B3n%26applied_filter_order%3D13%26applied_value_id%3DTUxBUENPUmFkZGIw%26applied_value_name%3DC%C3%B3rdoba%26applied_value_order%3D11%26applied_value_results%3D120%26is_custom%3Dfalse%26view_more_flag%3Dtrue"
response = ProductsSpider.process(url)
if response[:status] == :completed && response[:error].nil?
flash.now[:notice] = "Successfully scraped url"
else
flash.now[:alert] = response[:error]
end
rescue StandardError => e
flash.now[:alert] = "Error: #{e}"
end

i have code which implement upload song to database using plupload-jquery and show in datatable for management but song not saved to database

uploaded_song_datatable.rb --which is used for showing list of song in datatable.
class UploadedSongDatatable < AjaxDatatablesRails::Base
include AjaxDatatablesRails::Extensions::Kaminari
def_delegator :#view, :best_in_place
def_delegator :#view, :link_to
def_delegator :#view, :uploaded_song_path
def_delegator :#view, :autocomplete_album_name_albums_path
def_delegator :#view, :autocomplete_artist_name_artists_path
def_delegator :#view, :autocomplete_genre_name_genres_path
def_delegator :#view, :year_list
def_delegator :#view, :content_tag
def_delegator :#view, :image_tag
def sortable_columns
#sortable_columns ||= [
'UploadedSong.title',
'UploadedSong.artist',
'UploadedSong.album',
'UploadedSong.genre'
]
end
def searchable_columns
#searchable_columns ||= [
'UploadedSong.title',
'UploadedSong.artist',
'UploadedSong.album',
'UploadedSong.genre'
]
end
private
def data
records.map do |record|
[
# best_in_place(record, , :as => :checkbox, :collection => ['<input name="mark[]" type="checkbox">'.html_safe, '<input type="checkbox" checked="true">'.html_safe]),
nil,
"<input type='checkbox' class='checkBoxClass' name=\"songids[]\" value='#{record.id}' >",
best_in_place(record, :is_explicit, :as => :checkbox, :collection => ['<input type="checkbox">'.html_safe, '<input type="checkbox" checked="true">'.html_safe] , url: uploaded_song_path(record, field_to_update: 'is_explicit')),
best_in_place(record, :title, :display_with => lambda { |v| v.blank? ? "( No title )" : v }, url: uploaded_song_path(record, field_to_update: 'title')),
best_in_place(record, :artist, :display_with => lambda { |v| v.blank? ? "( No artist )" : v }, url: uploaded_song_path(record, field_to_update: 'artist'), html_attrs: { "data-autocomplete" => autocomplete_artist_name_artists_path, "object_id" => record.id.to_s }),
best_in_place(record, :album, :display_with => lambda { |v| v.blank? ? "( No album )" : v }, url: uploaded_song_path(record, field_to_update: 'album'), html_attrs: { "data-autocomplete" => autocomplete_album_name_albums_path }),
best_in_place(record, :genre, :display_with => lambda { |v| v.blank? ? "( No genre )" : v }, url: uploaded_song_path(record, field_to_update: 'genre'), html_attrs: { "data-autocomplete" => autocomplete_genre_name_genres_path }),
best_in_place(record, :year, :as => :select, :collection => year_list, :display_with => lambda { |v| v.blank? ? "( No year )" : v }, url: uploaded_song_path(record, field_to_update: 'year')),
best_in_place(record, :track, :display_with => lambda { |v| v.blank? ? "( No track )" : v }, url: uploaded_song_path(record, field_to_update: 'track')),
best_in_place(record, :comment, :display_with => lambda { |v| v.blank? ? "( No comment )" : v }, url: uploaded_song_path(record, field_to_update: 'comment')),
if record.cover_id.blank?
link_to("No Cover", "#cover_modal", data: {song_id: record.id, toggle: "modal", multiqueue: 'false'})
else
link_to("#") do
image_tag(record.cover.cover_pic.url, href: "#cover_modal", height: '50', width: '50', data: {song_id: record.id, toggle: "modal", src: record.cover.cover_pic.url, multiqueue: 'false'})
end
end,
link_to(uploaded_song_path(record), method: :delete, data: { confirm: "Are you sure to delete the song ?"}) do
content_tag :span, '', class: "glyphicon glyphicon-trash glyphicon-red"
end
]
end
end
def get_raw_records
UploadedSong.all
end
end
uploaded_song_controller.rb
require 'taglib'
class UploadedSongsController < ApplicationController
before_action :authenticate_user!
authorize_resource
respond_to :json, :html, :js
def index
if params[:from_modal]
sleep(10)
flash[:notice] = "Click 'Refresh', to view recently uploaded songs."
end
#songs = UploadedSong.count
respond_to do |format|
format.html
format.json { render json: UploadedSongDatatable.new(view_context) }
end
end
def new
#song = UploadedSong.new
end
def create
Rails.logger.debug params[:file]
extraction_path = Pathname.new("#{Rails.root}/public")
file_ext = File.extname(params[:file].original_filename)
original_file_name = params[:file].original_filename
tmp_file_base_name = File.basename(params[:file].path)
uploaded_tmp_file = "#{extraction_path}/#{tmp_file_base_name}"
uploaded_file = "#{extraction_path}/#{original_file_name}"
if params[:file].content_type == "application/zip"
Rails.logger.debug "moving #{params[:file].path} to #{extraction_path}"
FileUtils.mv(params[:file].path, extraction_path)
Rails.logger.debug "file moved"
if File.rename(uploaded_tmp_file, uploaded_file)
Resque.enqueue(ZipExtractor, uploaded_file, extraction_path.to_s, true, false)
Rails.logger.debug "Background job started"
head 200
else
File.delete(uploaded_tmp_file) if File.exist?(uploaded_tmp_file)
end
elsif %w(.mp3 .ogg .mp4 .m4a).include?(file_ext)
FileUtils.mv(params[:file].path, extraction_path)
if File.rename(uploaded_tmp_file, uploaded_file)
Rails.logger.info "renaming #{tmp_file_base_name} to #{original_file_name}"
Resque.enqueue(ZipExtractor, false, uploaded_file, false, false)
head 200
else
File.delete(uploaded_tmp_file) if File.exist?(uploaded_tmp_file)
head 200
end
else
File.delete(params[:file].path) if File.exist?(params[:file].path)
head 200
end
end
def edit
#song = UploadedSong.find(params[:id])
end
def update
#song = UploadedSong.find(params[:id])
#song.field_to_update = (params[:field_to_update])
if #song.update_attributes(uploaded_song_params)
Resque.enqueue(ZipExtractor, #song.id, false, false, #song.field_to_update)
end
respond_with_bip #song
end
def destroy
#song = UploadedSong.find(params[:id])
#song.destroy!
unless #song.cover_id.blank?
cover = Cover.find(#song.cover_id)
cover.destroy!
end
if session[:ids] == nil
respond_to do |format|
format.html { redirect_to uploaded_songs_url, notice: 'Song was successfully destroyed.' }
format.json { head :no_content }
end
else
session[:ids].delete(#song.id)
respond_to do |format|
format.html { redirect_to uploaded_songs_url, notice: 'Song was successfully destroyed.' }
format.json { head :no_content }
end
end
end
private
def uploaded_song_params
params.require(:uploaded_song).permit(:title, :artist, :album, :year, :track, :genre, :comment, :song_name, :attachment, :is_explicit)
end
def set_session_for_ids
if session[:ids] == nil
session[:ids] = Array.new
end
end
def update_music_metadata?(song)
TagLib::FileRef.open(song.attachment_url) do |fileref|
unless fileref.null?
tag = fileref.tag # true is for writing.
tag.title = song.title
tag.artist = song.artist
tag.album = song.album
tag.year = song.year.to_i
tag.track = song.track.to_i
tag.genre = song.genre
tag.comment = song.comment
if fileref.save
return true
else
return false
end
end
end
end
def update_song_name?(song)
file_handle = File.open(song.song_path)
dir_location = File.dirname(song.song_path)
file_ext = File.extname(song.song_path)
song_name = song.song_name + file_ext
song_path = dir_location + "/#{song_name}"
attachment = File.rename_file(file_handle, song_path)
if song.update_attributes({attachment: attachment, song_name: song_name, song_path: song_path})
return true
else
return false
end
end
end
uploaded_song.rb
require 'file_size_validator'
class UploadedSong < ActiveRecord::Base
belongs_to :cover
mount_uploader :attachment, AttachmentUploader
skip_callback :commit, :after, :remove_attachment!, if: Proc.new{ |s| s.file_keep == true }
validates :attachment, :file_size => { less_than: 200.megabytes }
attr_accessor :file_keep, :field_to_update
end
zip_extractor.rb
require 'taglib'
require 'zip'
class ZipExtractor
#queue = :songs_queue
def self.perform path_to_zip, destination_path, delete = false, field_to_update
if !path_to_zip.blank? and delete and !destination_path.blank? and !field_to_update
unzip(path_to_zip, destination_path)
Dir.glob("#{destination_path}" + '/*') do |music_file|
base_file_name = File.basename(music_file)
next if base_file_name.casecmp("__macosx") == 0
process_song(music_file)
end
end
if !path_to_zip and !delete and !destination_path.blank? and !field_to_update
process_song(destination_path)
end
if !path_to_zip.blank? and !delete and !destination_path and !field_to_update.blank?
log("processing song details update")
song = UploadedSong.find(path_to_zip)
song_details = nil
TagLib::FileRef.open(song.attachment_url) do |fileref|
unless fileref.null?
tag = fileref.tag
case field_to_update.to_s
when "title"
tag.title = song.title
when "artist"
tag.artist = song.artist
when "album"
tag.album = song.album
when "year"
tag.year = song.year.to_i
when "track"
tag.track = song.track.to_i
when "genre"
tag.genre = song.genre
when "comment"
tag.comment = song.comment
else
log 'No parameters for "field_to_update".'
end
unless fileref.save
TagLib::FileRef.open(song.attachment_url) do |fileref|
unless fileref.null?
tag = fileref.tag
song_details = {
title: tag.title,
artist: tag.artist,
album: tag.album,
year: tag.year,
track: tag.track,
genre: tag.genre,
comment: tag.comment,
is_explicit: false
}
end
end
if song_details[:title].downcase.include? 'explicit'
song_details[:is_explicit] = true
end
song.update_attributes(song_details)
end
end
end
end
end
def self.process_song(destination_path)
if %w(.mp3 .ogg .mp4 .m4a).include? File.extname(destination_path)
if %w(.ogg .mp4 .m4a).include? File.extname(destination_path)
destination_path = convert_video_to_audio(destination_path)
end
if %w(.mp3).include? File.extname(destination_path)
process_mp3(destination_path)
else
delete_file(destination_path)
end
else
delete_file(destination_path)
end
end
def self.process_mp3(destination_path)
song_details = extract_metadata(destination_path)
rename_file = File.dirname(destination_path) + "/1-----" + File.basename(destination_path)
extension = File.extname(destination_path)
cover_file_name = nil
rename = File.rename(destination_path, rename_file)
if rename == 0
transcoded_movie, cover_file_name = transcode_file(rename_file, destination_path)
if transcoded_movie.valid?
delete_file(rename_file)
song_details[:attachment] = File.open(destination_path) if File.exist?(destination_path)
# cover = nil
p song_details[:attachment]
unless cover_file_name.nil?
cover = Cover.new({name: File.basename(cover_file_name), cover_pic: File.open(cover_file_name)}) if File.exist?(cover_file_name)
end
song = UploadedSong.new(song_details)
if !cover.blank?
if cover.save
delete_file(cover_file_name)
song.cover_id = cover.id
if song.save
delete_file(destination_path)
end
end
else
p 9999999999999999999999999999999999999999999999999999
p song.valid?
p song.save
p song.errors.any?
p song.errors.full_messages
p 9999999999999999999999999999999999999999999999999999
if song.save!
delete_file(destination_path)
end
end
else
delete_file(destination_path)
delete_file(rename_file)
end
else
delete_file(destination_path)
end
end
def self.convert_video_to_audio(destination_path)
log "Found video file. Converting video to audio."
movie = FFMPEG::Movie.new(destination_path)
if movie.valid?
file_name_with_no_ext = File.basename(destination_path, "#{File.extname(destination_path)}")
out_file = "#{File.dirname(destination_path)}/#{file_name_with_no_ext}.mp3"
out_movie = movie.transcode(out_file)
if out_movie.valid?
delete_file(destination_path)
destination_path = out_file
end
end
return destination_path
end
def self.extract_metadata(destination_path)
log("extracting metadata from media file")
song_details = nil
TagLib::FileRef.open(destination_path) do |fileref|
unless fileref.null?
tag = fileref.tag
song_details =
{
title: tag.title.blank? ? 'Single' : tag.title,
artist: tag.artist.blank? ? 'Single' : tag.artist,
album: tag.album.blank? ? 'Single' : tag.album,
year: tag.year.blank? ? '' : tag.year,
track: tag.track.blank? ? '' : tag.track,
genre: tag.genre.blank? ? '' : tag.genre,
comment: tag.comment.blank? ? '' : tag.comment,
is_explicit: false
}
if song_details[:title].downcase.include? 'explicit'
song_details[:is_explicit] = true
end
if tag.title.blank?
tag.title = "Single"
fileref.save
elsif tag.artist.blank?
tag.artist = "Single"
fileref.save
elsif tag.album.blank?
tag.album = "Single"
fileref.save
end
end
end
return song_details
end
def self.transcode_file(rename_file, destination_path)
movie = FFMPEG::Movie.new(rename_file)
cover_file_name = nil
transcoded_movie = nil
p movie.valid?
if movie.valid?
log "ffmpeg validates file #{rename_file}"
if movie.video_stream == nil
options = {audio_codec: "libmp3lame", audio_bitrate: 320, audio_sample_rate: 44100, audio_channels: 2}
else
log "removing video stream from file and extracting cover"
cover_file_name = extract_image_from_file(rename_file)
# "-vn" flag is used to remove video_stream from mp3 file
options = {audio_codec: "libmp3lame", audio_bitrate: 320, audio_sample_rate: 44100, audio_channels: 2, custom: "-vn"}
end
transcoded_movie = movie.transcode(destination_path, options)
else
log "Unable to process media file."
delete_file(rename_file)
end
return transcoded_movie, cover_file_name
end
def self.extract_image_from_file(rename_file)
cover_file_name = nil
cover_path = "#{Rails.root}/public/covers/"
TagLib::MPEG::File.open(rename_file) do |fileref|
cover_tag = fileref.id3v2_tag
cover_img = cover_tag.frame_list('APIC').first
unless cover_img.blank?
ext = cover_img.mime_type.rpartition('/')[2]
o = [('a'..'i'), ('A'..'Z')].map { |i| i.to_a }.flatten
rand_string = (1..18).map { o[rand(o.length)] }.join
cover_file_name = "#{cover_path}#{File.basename(rename_file).chomp('.mp3').gsub('1-----','')}-#{rand_string}.#{ext}"
File.open(cover_file_name, "wb") { |f| f.write cover_img.picture }
log "cover extracted from media file."
end
end
return cover_file_name
end
def self.delete_file(filename)
File.delete(filename) if File.exist?(filename)
end
def self.log(message)
Rails.logger.debug "\n*********** #{message} ***************"
end
def self.unzip(path_to_zip, destination_path)
log "unzipping #{path_to_zip} \nto #{destination_path}"
Zip::File.open(path_to_zip) do |zip_file|
# log "zip file is #{zip_file}"
zip_file.each do |f|
f_path=File.join(destination_path, f.name)
FileUtils.mkdir_p(File.dirname(f_path))
a = zip_file.extract(f, f_path) unless File.exist?(f_path)
# log "file extraction complete"
# log a
end
log "after zip file loop"
end
# log "removing original zip file"
FileUtils.rm(path_to_zip)
# log "removed zip file from #{path_to_zip}"
end
end
in above means zip_extractor.rb I checked song.valid? it gives me false in rails 6 and error is cover must exist
and I have checked cover is nil but in rails 4 it gives true and also checked in this version also cover is nil but song saved in database in rails but not in rails 6. anyone have proper reason why it behave like this answer fast otherwise mailto: santu.essence#gmail.com

Getting the error "Error: wrong number of arguments (given 0, expected 1; required keyword: url)"

Im building a basic rails web scraper and im running into this error. Here is my scraper method and my scraper model too.
https://gyazo.com/d866cd8def5ac107ea8c13515faac989
class RestaurantsScraper < Kimurai::Base
#name = 'restaurants_scraper'
#engine = :mechanize
def self.process(url)
url = 'tripadvisor.com/Restaurants-g31892-Rogers_Arkansas.html'
#start_url = [url]
self.crawl!
end
def parse(response, url:, data: {})
response.xpath("//div[#class=_1llCuDZj]").each do |t|
item = {}
item[:title] = t.css('a._15_ydu6b')&.text&.squish&.gsub('[^0-9].', '')
item[:type] = t.css('span._1p0FLy4t')&.text&.squish
item[:reviews] = t.css('span.w726Ki5B').text&.squish
item[:top_reviews] = t.css('a._2uEVo25r _3mPt7dFq').text&.squish
Restaurant.where(item).first_or_create
end
end
end
def scrape
url = 'https://www.tripadvisor.com/Restaurants-g31892-Rogers_Arkansas.html'
response = RestaurantsScraper.process(url)
if response[:status] == :completed && response[:error].nil?
flash.now[:notice] = "Successfully scraped url"
else
flash.now[:alert] = response[:error]
end
rescue StandardError => e
flash.now[:alert] = "Error: #{e}"
end

Rails RSpec net-ssh mock return of second ssh request

I'm working on a web application that frequently access simulation data on a remote server. I want to create test for errors handling that might happen during these request.
The problem I currently have is I cannot seems to mock a request with my ssh_with_stderr method. The ssh method works fine.
This the code I'm trying to test:
# app/jobs/zip_files_sync_job.rb
class ZipFilesSyncJob < ApplicationJob
queue_as :default
discard_on ActiveJob::DeserializationError
def perform(simulation)
simulation.zip_files.each do |f|
if f.path.nil? && f.created_at < 6.hours.ago
f.state = 'error'
f.save!
next
end
next if f.path.nil?
_, errors = simulation.server.ssh_with_stderr("ls #{f.path.shellescape}")
if errors.blank?
f.size = f.simulation.server.ssh("stat -c %s #{f.path.shellescape}")
f.state = 'ready' if f.size.to_i.positive?
elsif f.state == 'ready' && errors.present?
f.state = 'error'
elsif f.state == 'zipping' && errors.present? && f.created_at < 6.hours.ago
f.state = 'error'
end
f.save!
end
end
end
And this is what I want to test:
# spec/jobs/zip_files_sync_job_spec.rb
require 'rails_helper'
RSpec.describe ZipFilesSyncJob, type: :job do
let(:private_group) { Group::PRIVATE }
let(:user) { FactoryBot.create :user }
let(:server) { FactoryBot.create :server, user: user, external_storage: false }
let(:simulation) { FactoryBot.create :simulation, user: user, group: private_group, server: server }
let(:zip_file) { FactoryBot.create :zip_file, simulation: simulation, path: 'test/zip_file', state: 'pending', size: '100' }
let(:zip_file_no_path) { FactoryBot.create :zip_file, simulation: simulation, path: nil, created_at: 10.hours.ago, state: 'pending' }
let(:ssh_connection) { double('net-ssh') }
before do
zip_file_no_path
allow(Net::SSH).to receive(:start).and_yield(ssh_connection)
end
def perform_zip_file_sync(zip_file)
perform_enqueued_jobs do
ZipFilesSyncJob.perform_now(simulation)
end
zip_file.reload
yield
allow(Net::SSH).to receive(:start).and_call_original
end
describe '#perform' do
include ActiveJob::TestHelper
#################################
##### This test works fine #####
#################################
context 'with no errors' do
before do
zip_file
end
it 'it will change the state to ready' do
allow(Net::SSH).to receive(:start).and_return('144371201')
perform_zip_file_sync(zip_file) do
expect(zip_file.state).to eq 'ready'
end
end
end
#############################################################################
##### This test fails because it does not return on the ssh_with_stderr #####
#############################################################################
context 'with errors' do
it 'will change the state to error' do
allow(Net::SSH).to receive(:start).and_return("[' ', 'Error with connection']")
perform_enqueued_jobs do
ZipFilesSyncJob.perform_now(simulation)
end
zip_file.reload
expect(zip_file.state).to eq 'error'
end
end
end
end
This the the code for the server connection. It uses the net-ssh gem
# app/models/server.rb
Class Server < ApplicationRecord
def ssh(command, storage = true, &block)
Net::SSH.start(hostname, username, port: port, keys: ["key"], non_interactive: true, timeout: 1) do |ssh|
ssh.exec! "cd #{folder.shellescape}; #{command}", &block
end
end
def ssh_with_stderr(command)
#output = ""
#errors = ""
begin
Net::SSH.start(hostname, username, port: port, keys: ["key"], non_interactive: true, timeout: 1) do |ssh|
ssh.exec! "cd #{folder.shellescape}; #{command}" do |_ch, stream, data|
if stream == :stderr
#errors += data
else
#output += data
end
end
end
rescue Net::SSH::Exception, Errno::ECONNREFUSED, Errno::EINVAL, Errno::EADDRNOTAVAIL => e
#output = nil
#errors = e.message
end
[#output, #errors]
end
With this mock
allow(Net::SSH).to receive(:start).and_return("[' ', 'Error with connection']")
the ssh_with_stderr looks like
def ssh_with_stderr(command)
#output = ""
#errors = ""
begin
[' ', 'Error with connection']
rescue Net::SSH::Exception, Errno::ECONNREFUSED, Errno::EINVAL, Errno::EADDRNOTAVAIL => e
#output = nil
#errors = e.message
end
[#output, #errors]
end
So it always returns ["",""] , and checking errors.blank? always positive.
Try to mock Net::SSH with and_raise instead of and_return, something like
allow(Net::SSH).to receive(:start).and_raise(Errno::ECONNREFUSED, "Error with connection")

WebMock stub data from Aws CognitoIdentityProvider

I have the following module in a Rails controller concern:
module AwsAuth
extend ActiveSupport::Concern
require 'aws-sdk'
def get_cognito_user(token)
cognitoidentityprovider = Aws::CognitoIdentityProvider::Client.new(region: ENV['AWS_REGION'])
begin
cognito_user = cognitoidentityprovider.get_user({ access_token: token })
puts cognito_user
return {"email" => cognito_user.username}
rescue StandardError => msg
puts "ERROR!"
puts msg
return {"error" => msg}
end
end
end
At the moment, puts cognito_user returns:
#<Aws::CognitoIdentityProvider::Types::GetUserResponse:0x7fe51b0013a8
mfa_options = nil,
user_attributes = nil,
username = nil
>
How can I stud the response in Rspec so that username and user_attributes are not nil ?
after playing around with yzalavin's suggestion... the following works for me...
allow_any_instance_of( AwsAuth )
.to receive(:get_cognito_user)
.and_return( JSON[ {email: "testy#example.com"}.to_json ] )

Resources