undefined method `last' for #<Hash:0x00007f303593d6d8> - ruby-on-rails

trying the below code in a custom sdk in Workato
poll: lambda do |connection, input, last_updated_at|
per_page = 1
last_updated_at = (last_updated_at || input['since']).to_time.utc.iso8601
candidates = get("https://api.stripe.com/v1/customers")
last_updated_at = candidates.last["created"] unless candidates.blank?
Getting an error
undefined method `last' for #Hash:0x00007f303593d6d8 at line:

There is no Hash#last method. Hashes do keep their insertion order, but you should conceptually treat them as unordered. The concept of the "last" element of a Hash simply does not make sense.

Related

`block in <main>': undefined method `[]' for nil:NilClass (NoMethodError)

I'm trying to load a remote JSON URL to eventually store it in an SQLite3 database.
I am loading the JSON alright (I think) and then looping through it to assign each JSON value to a variable which will then be built into a db.execute statement to store it into the database.
I am getting an error 'block in <main>': undefined method[]' for nil:NilClass (NoMethodError) when I run the code.
The link Undefined method '>' for nil:NilClass <NoMethodError> is full of information but I don't understand what's going on to be honest. I'm wondering if someone can explain to me where I'm going wrong in my understanding.
My code is:
require 'json'
require 'open-uri'
tournament_url = "http://www.pgatour.com/data/r/033/leaderboard-v2.json"
puts tournament_url
leaderboard = JSON.load(open(tournament_url))
no_of_players = leaderboard['leaderboard']['players'].length
puts "The number of players to be loaded is: #{no_of_players}"
data_array = Array.new
for i in 0..no_of_players
current_position = leaderboard['leaderboard']['players'][i]['current_position']
end
If I write any code after the end loop it won't execute.
If had also tried to do a check on the value returned by saying:
if (leaderboard['leaderboard']['players'][i]['current_position'].nil?)
current_position = ""
else
current_position = leaderboard['leaderboard']['players'][i]['current_position']
end
Range 0..no_of_players is inclusive.
You probably want to use exclusive version (note three dots):
0...no_of_players
or:
0..no_of_players-1
.lenth returns the number of array items - so the array position of the last item would be no_of_players.length - 1. Basically you get the error because on the last iteration of the loop you get nil.
Instead I might suggest using .each:
leaderboard['leaderboard']['players'].each do |player|
current_position = player['current_position']
end

How do I deal with view getting either ActiveRecord object or array of hashes returned to it

I have this chunk of code that returns either an ActiveRecord object or and array of hashes. The first "if" returns an arrays of hashes via sql query
if #parts_search_ids.any?
#part_groups = Kaminari.paginate_array(PartGroup.search_part_groups(#parts_search_ids)).page(params[:page]).per(25)
# #part_groups = Kaminari.paginate_array(PartGroup.search_part_groups(#parts_search_ids)).page(params[:page]).per(25)
# #part_groups = PartGroup.parts_group_by_name(#parts_search_ids).page(params[:page]).per(25)
elsif #filter == 'all_parts'
#part_groups = Kaminari.paginate_array(PartGroup.all).page(params[:page]).per(25)
else
#part_groups = Kaminari.paginate_array([]).page(params[:page]).per(25)
end
So depending on the condition I have I get either:
part_group = {"name"=>"170128", "part_category"=>"0", "critical_part"=>"f", "part_groups_count"=>"1", "project"=>"CW01"}
or
part_group = #<PartGroup id: 1249, name: "KIT.LTE.OVLY.HUA.3CAR", part_category_id: 278, created_at: "2013-12-03 01:32:32", updated_at: "2013-12-03 01:32:32", always_show_group: false, critical_part: false>
as I loop through the part_groups array of hashes I get:
undefined method `name' for #
What is the best way to deal with this?
You could certainly have logic in your views that either calls a method on a Ruby object or treats it like a hash, but it would be cleaner (and a better practice) for the method to return the same type of objects.
So, in the appropriate branch of you if/elsif/else, either you convert the Ruby objects to Hashes or the Hashes to Ruby objects.
The first is the easiest, turning Ruby objects into hashes:
#part_groups = #part_groups.map(&:attributes)
The second, to turn a Hash into an instance of your class you can do
#part_groups = #part_groups.map { |pg| PartGroup.instantiate pg }.
Of course, you could just treat the Ruby object like a Hash: part_group['name'] will give you what you want from either the hash or the Ruby object. But then the method would still be returning different things, potentially leading to the same problem or just confusion in the future.

undefined method `take' for #<ActiveRecord::QueryMethods::WhereChain:0x00000107609598>

I am trying to select all profiles where a.blocked?(p) returns false!
However I am getting an error.
in a method in model
p = self.find_by_email(email)
all.find_by { |a| a.blocked?(p) }.order('random()')
error
undefined method `take' for #<ActiveRecord::QueryMethods::WhereChain:0x00000107609598>
find_by does not take a block, but rather conditions in the form of a hash, array, or string. See the documentation: http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find_by
If you can't replicate blocked? in SQL, you'll have to do the filtering in Ruby like:
all.find_all { |a| a.blocked?(p) }.shuffle
Because that's doing the filtering and sorting in Ruby rather than SQL, it will be slower.

Rails 3 - NoMethodError: undefined method for nil:NilClass in each Iteration

I'm iterating over an array of instances of a Rails model. Here is my code:
product_details.each do |product_detail|
product_detail.label = Backend::ProductGroup.where(product_group_number: product_detail.product_group).first.label
end
The attribute 'label' from 'product_detail' isn't an attribute from my Rails ActiveRecord model. I added it with attr_accessor in my class definition. I did this, because I wanted to add this attribute dynamically, only when I need to do this. When I ran the code without the 'each' iteration in my rails console it works just fine. But when I execute the above code I get the following error message:
NoMethodError: undefined method 'label' for nil:NilClass
Did I do something obviously wrong?
Many thanks in advance.
You likely have several product_detail items that have no matching product_group. So calling .first on the empty collection returns nil. To get around the error, you can test if the product_group was found before proceeding:
product_details.each do |product_detail|
product_group = Backend::ProductGroup.where(product_group_number: product_detail.product_group).first
product_detail.label = product_group.label if product_group
end
You can also do this more efficiently like so:
group_labels = BackEnd::ProductGroup.
where(product_group_number: product_details.map(&:product_group)).
inject({}){|m, g| m[g.product_group_number] = g.label; m}
product_details.each do |product_detail|
product_detail.label = group_labels[product_detail.product_group]
end
This will result in a single database call to grab all related groups, and put the labels in a keyed hash for easy discovery and assignment.

undefined method `<<' for nil:NilClass got this error while merging instance variables

In my controller i am merging the results of two different instance variables into one instance variable and i got an following error:
undefined method `<<' for nil:NilClass
Here is my controller code
#conversational = InterestType.where("institution_id = ? or global = ? and category_id = ?", current_user.profile.institution_id, true, 1).first
#commercial = InterestType.where("institution_id = ? or global = ? and category_id = ?", current_user.profile.institution_id, true, 2).limit(17)
#user_interest_types << #conversational
#user_interest_types << #commercial
How can i get over of this error or what is the good way to get following result.
I want to display first conversational interest type then other 17 commercial interest types.
If you want to append to an array you have two options and here you must pay attention to what you're adding:
# Define an empty array
#user_interest_types = [ ]
# Add a single element to an array
#user_interest_types << #conversational
# Append an array to an array
#user_interest_types += #commercial
If you use << for both operations you end up pushing an array into an array and the resulting structure has multiple layers. You can see this if you call inspect on the result.
If you want a nested array:
#user_interest_types = [#conversational, #commercial]
# gives [it1, [it2, it3, it4]]
Or if you prefer a flat array:
#user_interest_types = [#conversational, *#commercial]
# gives [it1, it2, it3, it4]
Assuming #conversational = it1 and #commercial = [it2, it3, it4]

Resources