Why does User.all.each {|u| puts u.id} print all fields? - ruby-on-rails

The following code:
User.all.each {|u| puts u.id}
Prints out all the fields for all records.
How can I change it to only print the id field?

I was unable to replicate this behavior but if you are looking at this in console you may be mistaking the fact that #each returns self (and self, a big array of User objects, is then inspected) for the call to each printing all fields. Can you instead run User.all.each {|u| puts u.id}; nil to have the console return nil after the each and see if the behavior persists?

If you run puts u, does it give a hash or an object? If hash, then use puts u[:id] or puts u['id'] rather than puts u.id.

If you are running this irb or rails console, it should print out just the IDs but then the return from your code is the set of users which the console will then print out. Scroll up and you will see the output you expect followed by the print out of all the user objects with full details.

Related

Block is not entered on a ActiveRecord_Relation

I am new to Ruby and RoR.
I have a class method that looks like this:
def self.show_all_expired
puts "\r\n COUNT: #{self.expired.all.count}\r\n"
self.expired.all do |s|
puts "\r\n COUNT: #{s}\r\n"
end
puts "\r\nEND\r\n"
end
When I run it from the console I get this output:
As you can see the subscriptions collection is not iterated and the block body is not entered at all. But the count of the query is 31, so there must be records. Why do block is not executed?
Looking at the docs you can see that all doesn't expect a block. It just returns the ActiveRecord::Relation scope object.
Instead, you want to use each which calls the given block once for each element in row collection:
self.expired.each do |s|
puts "\r\n Subscription: #{s.inspect}\r\n"
end
Or find_each if you are dealing with a larger number of records.

How to access raw SQL statement generated by update_all (ActiveRecord method)

I'm just wondering if there's a way to access the raw SQL that's executed for an update_all ActiveRecord request. As an example, take the simple example below:
Something.update_all( ["to_update = ?"], ["id = ?" my_id] )
In the rails console I can see the raw SQL statement so I'm guessing it's available for me to access in some way?
PS - I'm specifically interested in update_all and can't change it to anything else.
Thanks!
If you look at the way update_all is implemented you can't call to_sql on it like you can on relations since it executes directly and returns an integer (the number of rows executed).
There is no way to tap into the flow or get the desired result except by duplicating the entire method and changing the last line:
module ActiveRecord
# = Active Record \Relation
class Relation
def update_all_to_sql(updates)
raise ArgumentError, "Empty list of attributes to change" if updates.blank?
if eager_loading?
relation = apply_join_dependency
return relation.update_all(updates)
end
stmt = Arel::UpdateManager.new
stmt.set Arel.sql(#klass.sanitize_sql_for_assignment(updates))
stmt.table(table)
if has_join_values? || offset_value
#klass.connection.join_to_update(stmt, arel, arel_attribute(primary_key))
else
stmt.key = arel_attribute(primary_key)
stmt.take(arel.limit)
stmt.order(*arel.orders)
stmt.wheres = arel.constraints
end
#- #klass.connection.update stmt, "#{#klass} Update All"
stmt.to_sql
end
end
end
The reason you see the log statements is that they are logged by the connection when it executes the statements. While you can override the logging its not really possible to do it for calls from a single AR method.
If you have set RAILS_LOG_LEVEL=debug Rails shows you which SQL statement it executed.
# Start Rails console in debug mode
$ RAILS_LOG_LEVEL=debug rails c
# Run your query
[1] pry(main)> Something.update_all( ["to_update = ?"], ["id = ?" my_id] )
SQL (619.8ms) UPDATE "somethings" WHERE id = 123 SET to_update = my_id;
# ^it prints out the query it executed

Accessing Hash Keys with user inputted variables,Nil value No method error NoMethodError

Hi i had created a small ruby project which consists of JSON file. I stored the JSON data into hash keys. AND worte a method to access the data which is present in hash key using user input. But when i try to send use the user input i am getting this error
how_many_ingredients': undefined methodkeys' for nil:NilClass (NoMethodError)
I found this link with same question and tried that solution but still i'm getting the same error
Accessing Hash Keys with user inputted variables, NoMethodError
File one where all the methods are written
require 'json'
class Methods
attr_accessor :name, :text
def initilize(name)
#name = name
#text = text
end
def how_many_ingredients(text)
puts 'text'
file = File.read('a.json')
hash = JSON.parse(file)
#puts hash['recipes']['pizza'].keys
puts hash['recipes'][text].keys
end
end
File 2 where how_Many_ingredients method is accessed, I can see that the variable is passed to that method
require './1'
class Hello < Methods
person = Methods.new
person.test
puts "enter recipie"
person.name
str = gets
person.how_many_ingredients str
end
Note that when you use gets, the input can contain newline and carriage return characters. You'll need to use gets.chomp to filter these. This is likely the cause of the issue in your program.
Compare the following two:
> puts gets.size
"Hello!"
# 7
> puts gets.chomp.size
"Hello!"
# 6
Note that you'll still need to extend your program to account for user inputted keys that are not in your hash.
Your code assumes that there will always be a hash stored at hash['recipes'][text] - you need to cater to the cases where it isn't.
A simple way to do this is to work your way down through the hash with && symbols - if any step is nil (or false), the line will return nil (or false) rather than exploding. eg
puts hash['recipes'] && hash['recipes'][text].is_a?(Hash) && hash['recipes'][text].keys
Note i'm testing that hash['recipes'][text] is a hash (rather than just a string for example) before calling .keys on it.

Output value of puts in Ruby

I'm probably missing something really obvious here. I have the following Ruby method:
def pair_array
return self.pair.each_slice(2) {
|x| puts x.join(" & ")
}.to_s
end
When I try to display the value of this method in my Rails view by calling #team.pair_array nothing appears, but the correct value gets printed on the console. I know this is probably because I'm using puts. How can I get the result of this method to display in my view?
You're confusing printing with returning a value. puts returns nil, and each_slice does not return the result of the block anyway. What you want is this:
def pair_array
pair.each_slice(2).map {|arr| arr.join ' & '}
end

Ruby - how to get and loop through all the values in an object returned from the db?

I have this line:
#users = database['users'].find(:all).limit(10)
it returns this object:
<Mongo::Cursor:0x8759a858 namespace='app-development.users' #selector=:all #cursor_id=>
and what I thought was that it has a collection of the 10 users it got from the database. Is that correct? I tried iterating through it like this:
#users.each {
|info|
logger.debug ".....................single user: " + info.inspect
}
but I got this error:
BSON::InvalidDocument (BSON.serialize takes a Hash but got a Symbol):
Help much appreciarted!
I'm not framiliar with mongo but try this:
#users.each do |info|
logger.debug ".....................single user: #{info.inspect}"
end
The #{} allows you to evaluate ruby code within a double quoted string.
If you want to see the litteral result try appending to_a to the query. This should give you an array with ten items in it.
#users = database['users'].find(:all).limit(10).to_a

Resources