How to let the SQL results display in Rails's log? - ruby-on-rails-3

I don't know whether this is a reasonable request. I hope to see the result in the log file such as log/development.log, Now the ActiveRecord::Base.logger.level = 0 and there is only the SQL statements:
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = 3 LIMIT 1
Excursion Load (0.3ms) SELECT "excursions".* FROM "excursions" WHERE "excursions"."id" = $1 LIMIT 1 [["id", "5"]]
Actor Load (0.5ms) SELECT "actors".* FROM "actors" WHERE "actors"."id" = 4 LIMIT 1
There is no results. I know in the 'rails console', when using ActiveRecord::Base.logger = Logger.new(STDOUT), I see the statements and corresponding results:
1.9.3-p551 :001 > ActiveRecord::Base.logger = Logger.new(STDOUT)
=> #<Logger:0x007f80441364d0 #progname=nil, #level=0, #default_formatter=#<Logger::Formatter:0x007f8044135c60 #datetime_format=nil>, #formatter=# <Logger::SimpleFormatter:0x007f8044134bd0 #datetime_format=nil>, #logdev=#<Logger::LogDevice:0x007f8044135440 #shift_size=nil, #shift_age=nil, #filename=nil, #dev=#<IO:<STDOUT>>, #mutex=# <Logger::LogDevice::LogDeviceMutex:0x007f8044135378 #mon_owner=nil, #mon_count=0, #mon_mutex=#<Mutex:0x007f8044134c98>>>>
1.9.3-p551 :002 > User.first
User Load (1.0ms) SELECT "users".* FROM "users" LIMIT 1
Actor Load (0.8ms) SELECT "actors".* FROM "actors" WHERE "actors"."id" = 2 LIMIT 1
ActivityObject Load (0.9ms) SELECT "activity_objects".* FROM "activity_objects" WHERE "activity_objects"."id" = 2 LIMIT 1
=> #<User id: 1, encrypted_password: "$2a$10$wFj.Q9XX0ua16BF0.SIps.VjnfVi8/6egicirc/SFxw3...", password_salt: nil, reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, authentication_token: nil, created_at: "2015-03-25 22:14:32", updated_at: "2015-03-25 22:14:32", actor_id: 2, language: nil, connected: false, status: "chat", chat_enabled: true, occupation: nil, invitation_token: nil, invitation_created_at: nil, invitation_sent_at: nil, invitation_accepted_at: nil, invitation_limit: nil, invited_by_id: nil, invited_by_type: nil>
What options I can set for this? Thanks in advance!

I researched some ActiveRecord (v3.2.21) code, It seems that there is no option about the SQL result. The above log User Load (1.0ms) SELECT "users".* FROM "users" LIMIT 1 is finished through callingActiveSupport::Notifications.instrument():
# query_cache.rb
def cache_sql(sql, binds)
result =
if #query_cache[sql].key?(binds)
ActiveSupport::Notifications.instrument("sql.active_record",
:sql => sql, :binds => binds, :name => "CACHE", :connection_id => object_id)
#query_cache[sql][binds]
else
#query_cache[sql][binds] = yield
end
result.collect { |row| row.dup }
end
So if I want to see the result in log I can add a log statement:
logger.info "#{result}"
result.collect { |row| row.dup }

Related

Uniqueness validation returning false non-uniqueness

Adding states to an empty database, where State validates :name, uniqueness: true.
Again, the DB is empty!
State.create(name:"Alabama")
(0.2ms) BEGIN
State Exists (0.6ms) SELECT 1 AS one FROM "states" WHERE "states"."name" = $1 LIMIT $2 [["name", "Alabama"], ["LIMIT", 1]]
(0.3ms) ROLLBACK
=> #<State:0x00007ffb711c3c60 id: nil, name: "Alabama", region_id: nil, created_at: nil, updated_at: nil>
State.all
State Load (0.5ms) SELECT "states".* FROM "states"
=> []
Why does it say this state exists when NO states exist???
When I get rid of the uniqueness validation, it's still acting funny:
State.all
State Load (0.7ms) SELECT "states".* FROM "states"
=> []

select vs distinct vs uniq?

I am confused by Ruby's ActiveRecord uniq method. I am using it to try to get back an array of complete objects, not just a particular field.
In my Padrino app script, which saves newspaper names and scores as Score objects, the uniq method by attribute on an ActiveRecord Relation is not working, and neither is distinct, with or without SQL syntax. Can anyone explain what is going on?
class Score < ActiveRecord::Base
def self.from_today
self.where('created_at > ?', Date.today)
end
end
scores = Score.from_today
scores.class
=> Score::ActiveRecord_Relation
scores.first
=> #<Score id: 123, score: -2.55, source: "Mail", created_at: "2016-08-11 04:29:24", updated_at: "2016-08-11 04:29:24">
scores.map(&:source)
=> ["Mail", "Guardian", "Telegraph", "Independent", "Express", "Mail"]
scores.uniq(:source).count
=> 6
scores.distinct(:source).count
=> 6
scores.select('distinct (SOURCE)').count
=> 5 #AHA, it works!
scores.select(:source).distinct
=> #<ActiveRecord::Relation [#<Score id: nil, source: "Telegraph">, #<Score id: nil, source: "Mail">, #<Score id: nil, source: "Independent">, #<Score id: nil, source: "Express">, #<Score id: nil, source: "Guardian">]>
#oops, no it doesn't
In Rails 5 distinct has no parameter. In Rails 4.2 the parameter is only true or false. When true, return distinct records, when false return none distinct records. uniq is in this case only an alias for distinct
So for Rails 4
scores.select(:source).distinct.count is what you want. This restricts distinct to column source

Query to find "active" ads in Rails

I'm building an ad manager that has the following Schema:
<Campaign id: nil, target_id: nil, date_view_based: nil, start_date: nil, end_date: nil, max_views: nil, cur_views: nil, link_to: nil, alt_data: nil, title_attr: nil, created_at: nil, updated_at: nil, user_id: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, link_clicked: nil, name: nil>
What I need is a way to create a method that will run like this...
Campaigns.current?
And output an array of something like this
Campaign.where('date_view_based =? AND end_date >= ? AND start_date <= ?', "Date", Date.today.strftime('%m/%d/%Y'), Date.today.strftime('%m/%d/%Y')).concat(Campaign.where('date_view_based = ? AND max_views >= ?, "View", :cur_views))
However, the Campaign.where('max_views >= ?, :cur_views) doesn't work, so how can I compare these two attributes? Surely there must be a better way to do this any suggestions would be appreciated.
Sorry I thought I had included the structure but I guess I didn't: Campaign.new returns:
#<Campaign id: nil, target_id: nil, date_view_based: nil, start_date: nil, end_date: nil, max_views: nil, cur_views: nil, created_at: nil, updated_at: nil, name: nil>
How about this?
class Campaign < ActiveRecord::Base
# ...
def self.current
date_view_based_enum = %W(Date View)
date = Date.today.strftime('%m/%d/%Y')
where("((start_date <= ? AND end_date >= ?) OR (max_views >= cur_views)) AND date_view_based IN (?)", date, date, date_view_based_enum)
end
end

Set ActiveRecord Scopes In A Loop

Why doesn't this work?
class Foo
...
Status.each do |status|
scope status, where(status: status)
end
...
end
Now Foo.new it returns not an instance of Foo but an ActiveRecord::Relation.
Try this in ruby 1.9
Status.each do |status|
scope status, -> { where(status: status) }
end
or in previous ruby versions
Status.each do |status|
scope status, lambda { where(status: status) }
end
-- EDIT --
I guess your problem is somewhere else, since this code is working for me:
class Agency < ActiveRecord::Base
attr_accessible :logo, :name
validate :name, presence: true, uniqueness: true
NAMES = %w(john matt david)
NAMES.each do |name|
scope name, -> { where(name: name) }
end
end
I can create new models just fine and use the scopes
irb(main):003:0> Agency.new
=> #<Agency id: nil, name: nil, logo: nil, created_at: nil, updated_at: nil>
irb(main):004:0> Agency.matt
Agency Load (0.5ms) SELECT "agencies".* FROM "agencies" WHERE "agencies"."name" = 'matt'
=> []
irb(main):005:0> Agency.john
Agency Load (0.3ms) SELECT "agencies".* FROM "agencies" WHERE "agencies"."name" = 'john'
=> []
irb(main):006:0> Agency.david
Agency Load (0.3ms) SELECT "agencies".* FROM "agencies" WHERE "agencies"."name" = 'david'
=> []

How to get old value of column in a callback?

On after_update, in my model. How can I get the old value of a column?
changed_attributes() method of your model will get you a hash of changed attributes with their original values, even after_udpate. More info and more related methods here.
class MyModel < ActiveRecord::Base
after_update :log_changed
def log_changed
puts "changed attributes:"
puts changed_attributes.inspect
end
end
... gives the following in the console:
$ rails console
Loading development environment (Rails 3.0.7)
test(dev)> m = MyModel.first
=> #<MyModel id: 134611365, name: "oldname", created_at: "2011-09-16 10:27:53", updated_at: "2011-09-20 11:58:11">
test(dev)> m.name = 'newname'
=> "newname"
test(dev)> m.save
SQL (0.2ms) BEGIN
SQL (0.4ms) SHOW TABLES
AREL (0.2ms) UPDATE `mymodels` SET `updated_at` = '2011-09-20 12:07:34', `name` = 'newname' WHERE `mymodels`.`id` = 134611365
changed attributes:
{"name"=>"oldname", "updated_at"=>Tue, 20 Sep 2011 11:58:11 UTC +00:00}
SQL (83.9ms) COMMIT
=> true
test(dev)> m.changed_attributes
=> {}