How to increment the loop if it does not match the id? - ruby-on-rails

I'm working on a code which displays the images from the AWS server. But I'm facing trouble in looping the code.
It works fine for the 1st display but it is not going further (I've to display upto 6 images)
code for this -
def get_image_urls(user)
user_identifications = user.user_identifications.where(current_flag: true).order(:id_dl)
urls = []
keys = []
if !user_identifications.empty? && !user_identifications.nil?
user_identifications.each_with_index do |each_id, index|
obj = S3_BUCKET.object(each_id.aws_key)
urls << {each_id.id_dl=> obj.presigned_url(:get)}
keys << {each_id.id_dl=> each_id.aws_key}
end
end
return urls, keys
end
How to increment the loop based on checking the id and user.identifications value?

reject all empty values and then iterate users_identifications.
Like:
sanitized_identifications = users_identifications.reject(&:blank?)
sanitized_identifications.each_with_index do |identification, _index|
# Now if you want to skip an iteration based on some condition, try `next`, like:
# next if some_condition
# in you case
obj = S3_BUCKET.object(each_id.aws_key)
next if obj.blank?
urls << {each_id.id_dl=> obj.presigned_url(:get)}
keys << {each_id.id_dl=> each_id.aws_key}
end
UPDATE
# ...
user_identifications.each_with_index do |each_id, index|
begin
obj = S3_BUCKET.object(each_id.aws_key)
urls << {each_id.id_dl=> obj.presigned_url(:get)}
keys << {each_id.id_dl=> each_id.aws_key}
rescue => e
next
end
end
#...
Cheers!

Related

Iterate through array of column names to pass to uniq.pluck()?

I have multiple columns I need to pull unique values from and compile an array of each unique value. Using uniq.pluck(:column_name) works, but how do I iterate over an array of column names?
react = []
fields = [reactivity_1, reactivity_2, reactivity_3, reactivity_4]
fields.each do |field|
puts "Parsing #{field}"
Raw.all.uniq.pluck(field).each do |r|
unless react.include? r
puts "Adding #{r} to Array."
react << r
else
puts "#{r} Exists."
end
end
end
Error:
NameError: undefined local variable or method `reactivity_1' for main:Object
You will need to make the column names strings or symbols, like this Ruby thinks it is a local varaible or method.
react = Set.new
fields = [:reactivity_1, :reactivity_2, :reactivity_3, :reactivity_4]
fields.each do |field|
puts "Parsing #{field}"
Raw.all.uniq.pluck(field).each do |r|
react << r
end
end
If you want to make sure that a collection does not contain duplicate, you can use a Set:
require "set"
set = Set.new
set << "foo"
set << "bar"
set << "bar"
puts set.size #> 2
I've rewritten your code sample to use Set.
Can you describe what you are trying to achieve? Perhaps there is an easier way to get the data out of the DB.

How do I iterate through a table and create a hash for each value?

I have two tables. One for accounts and another for keywords. I would like to iterate over all of the keywords and store each one in a hash--grouped by the account ID that added the keyword. The code that I have below doesn't add each keyword to the hash. For example, I have an account that has 2 keyword entries. My code skips the first entry and only adds the second entry to the hash.
#keyword_hash = {}
#account.each do |key, value|
#keywords.where(:profile_id => key).each do |keyword|
#keyword_hash[key] = keyword.entry
end
end
puts #keyword_hash
How can I modify the above code so that I add each keyword entry for a particular account to the hash?
I would like to be able to do #keyword_hash[6] and get keyword1, keyword2, keyword3, etc. for that account. Thanks!
Make an array [keyword1, keyword2, keyword3, etc.] and then add it to hash
**
#keyword_hash = {}
#account.each do |key, value|
arr = []
#keywords.where(:profile_id => key).each do |keyword|
arr << keyword.entry
end
#keyword_hash[key] = arr
end
puts #keyword_hash
**
Try this code
#keyword_hash = Hash.new { |h, k| h[k] = [] }
#account.each do |key, value|
#keywords.where(:profile_id => key).each do |keyword|
#keyword_hash[key] << keyword.entry
end
end
puts #keyword_hash
The mistake you are doing is that you are storing a single value against each key in your #keyword_hash hash. so when your code writes second value against account key, it replaces the previous value instead of adding second one.
Edit: Thank you #mudasobwa for correction regarding shared default value.
#keyword_hash = Hash.new { |hash, key| hash[key] = [] }
#keywords.group_by{ |k| k.profile_id }.each do |key,value|
#keyword_hash[key] = value.map(&:entry)
end
puts #keyword_hash
After doing some more research, I found the above solution. I used #jvillian's suggestion about group_by, and I found this article that showed me how to initialize the hash.

Rake task handle 404

I am using a rake task to take data from one csv, call the shopify api using that data, and save the response to another CSV. The problem is I have no error handler in place so that if the shopify api cannot find the resource I provided, the whole task gets aborted. What is the best way to handle the error so that if the resource is not found in Shopify, simply skip it and proceed to the next row?
The line calling the shopify API in the code below is:
variant = ShopifyAPI::Variant.find(vid)
namespace :replace do
desc "replace variant id with variant sku"
task :sku => :environment do
file="db/master-list-3-28.csv"
newFile = Rails.root.join('lib/assets', 'newFile.csv')
CSV.open(newFile, "a+") do |csv|
CSV.foreach(file) do |row|
msku, namespace, key, valueType, value = row
valueArray = value.split('|')
newValueString = ""
valueArray.each_with_index do |v, index|
recArray = v.split('*')
handle = recArray[0]
vid = recArray[1]
newValueString << handle
newValueString << "*"
# use api call to retrieve variant sku using handle and vid
#replace vid with sku and save to csv
variant = ShopifyAPI::Variant.find(vid)
sleep 1
# puts variant.sku
newValueString << variant.sku
if index < 2
newValueString << "|"
end
end
#end of value save the newvaluestring to new csv
csv << [newValueString]
end
end
end
end
Here's a simple way to get it done:
begin
variant = ShopifyAPI::Variant.find(vid)
rescue
next
end
If an exception is raised the stuff in rescue happens.

Adding assert function

I'm new to Ruby on Rails and going through Learn Ruby the Hard Way right now. In the lesson I am supposed to add the Assert feature to Dict.rb (shown below). Would anyone know how I can go about doing this? Every time I try I receive an error.
module Dict
#Creates a new function that makes a Dictionary. This is done through creating the
# aDict variable that has an array in which num_buckets array is placed inside.
# These buckets will be used to hold the contents of the Dict and later aDict.length
# is used to find out how many buckets there are.
def Dict.new(num_buckets=256)
# Initializes a Dict with the given number of buckets.
aDict = []
(0...num_buckets).each do |i|
aDict.push([])
end
return aDict
end
# Converts a string to a number using the bult-in Ruby 'hash' function
# Once I have a number for the key, I use the % operator and aDict.length to get a
# bucket where the remainder can go.
def Dict.hash_key(aDict, key)
# Given a key this will create a number and then convert it to an index for the
# aDict's buckets
return key.hash % aDict.length
end
# Uses hash_key to find a bucket that the key could be in. Using bucket_id I can get
# the bucket where the key could be. By using the modulus operator I know it will fit
# into the aDict array of 256.
def Dict.get_bucket(aDict, key)
# Given a key, find the bucket where it would go.
bucket_id = Dict.hash_key(aDict, key)
return aDict[bucket_id]
end
# Uses get_slot to get the (i, k, v) and returns the v (value) only.
def Dict.get_slot(aDict, key, default=nil)
# Returns the index, key and value of a slot found in a bucket.
bucket = Dict.get_bucket(aDict, key)
bucket.each_with_index do |kv, i|
k, v = kv
if key == k
return i, k, v
end
end
return -1, key, default
end
def Dict.get(aDict, key, default=nil)
# Gets the value in a bucket for the given key or the default.
i, k, v = Dict.get_slot(aDict, key, default=default)
return v
end
# Sets a key/value pair by getting the bucket and appending the new (key, value) to it.
# First you have to get the bucket, see if the key already exists, if it does then
# replace it, if it doesn't get replaced then append it.
def Dict.set(aDict, key, value)
# Sets the key to the value, replacing any existing value.
bucket = Dict.get_bucket(aDict, key)
i, k, v = Dict.get_slot(aDict, key)
if i >= 0
bucket[i] = [key, value]
else
bucket.push([key, value])
end
end
# Deletes a key by getting the bucket, searching for key in it and deleting it form the
# array.
def Dict.delete(aDict, key)
# Deletes the given key from the Dict.
bucket = Dict.get_bucket(aDict, key)
(0...bucket.length).each do |i|
k, v = bucket[i]
if key == k
bucket.delete_at(i)
break
end
end
end
# goes through each slot in each bucket and prints out what's in the Dict.
def Dict.list(aDict)
# Prints out what's in the Dict.
aDict.each do |bucket|
if bucket
bucket.each {|k, v| puts k, v}
end
end
end
end
I am using the following script to run methods from the module Dict.rb:
require './dict.rb'
# create a mapping of state to abbreviation
states = Dict.new()
Dict.set(states, 'Oregon', 'OR')
Dict.set(states, 'Florida', 'FL')
Dict.set(states, 'California', 'CA')
Dict.set(states, 'New York', 'NY')
Dict.set(states, 'Michigan', 'MI')
# create a basic set of states and some cities in them
cities = Dict.new()
Dict.set(cities, 'CA', 'San Francisco')
Dict.set(cities, 'MI', 'Detroit')
Dict.set(cities, 'FL', 'Jacksonville')
# add some more cities
Dict.set(cities, 'NY', 'New York')
Dict.set(cities, 'OR', 'Portland')
# puts out some cities
puts '-' * 10
puts "NY State has: #{Dict.get(cities, 'NY')}"
puts "OR State has: #{Dict.get(cities, 'OR')}"
# puts some states
puts '-' * 10
puts "Michigan's abbreviation is: #{Dict.get(states, 'Michigan')}"
puts "Florida's abbreviation is: #{Dict.get(states, 'Florida')}"
# do it by using the state then cities dict
puts '-' * 10
puts "Michigan has: #{Dict.get(cities, Dict.get(states, 'Michigan'))}"
puts "Florida has: #{Dict.get(cities, Dict.get(states, 'Florida'))}"
# puts every state abbreviation
puts '-' * 10
Dict.list(states)
# puts every city in state
puts '-' * 10
Dict.list(cities)
puts '-' * 10
# by default ruby says "nil" when something isn't in there
state = Dict.get(states, 'Texas')
if !state
puts "Sorry, no Texas."
end
# default values using ||= with the nil result
city = Dict.get(cities, 'TX', 'Does Not Exist')
puts "The city for the state 'TX' is: #{city}"
There is no "assert" method by default in Ruby. That's why you are getting an "undefined method" error. You either need to implement this method yourself or use a testing framework like Minitest or Rspec.
If you want to implement a simple assert method yourself it would be something like this:
def assert(first_item, second_item)
unless first_item == second_item
puts "[Error] #{first_item} does not equal #{second_item}"
end
end
And then use it like this:
assert(Dict.get(cities, 'NY'), 'New York')
The idea is that assertions help you make sure your code returns the expected output without having to check it manually.

Taking a query and loading an array with unique values from one of the query fields?

Rails 2.3.5
I have a query whose results contain a "week_of" date stamp. To work with the results, I need a unique list of the "week_of" dates in a seperate array.
I did what I was wanting like below, I was just wondering if there's an easier/shorter way to do something like this (take a query and then load an array with the unique values in one of the query fields). Thanks!
#test = []
#my_query.each do |x|
if #test.size > 0
flag = 0
#test.each do |t|
if t == x.week_of
flag = 1
end
end
if flag == 0
#test << x.week_of
end
else
#test << x.week_of
end
end
try this
#test = []
#my_query.each do |x|
#test << x.week_of
end
#test.uniq!
The following code will turn the list of results into a list of unique week_of entries:
#my_query.map do |x| x.week_of end.uniq
Both map and uniq are explained in http://www.ruby-doc.org/core-1.9.3/Array.html.

Resources