Why does this ActiveRecord method raise a NameError? - ruby-on-rails

Can anyone tell me what's wrong with this code?
class Dataset < ActiveRecord::Base
has_many :dataitems
def self.get_hash(dataset_id)
#dataitems = Dataset.find_by_id(24).dataitems
#dataitems.each do |di|
dataset_hash[di.axis0value] = di.axis1value #assign value for each category value
end
return dataset_hash
end
When run in dev environment it gives the following error in development.log:
rocessing BleeController#refresh_my_graph (for
127.0.0.1 at 2009-05-07 21:58:54) [GET] Session ID: 8179153011071621ae181e852b03fbe1 Parameters: {"dataset_id"=>"24", "action"=>"refresh_my_graph", "controller"=>"blee"} [4;36;1mDataset Columns (0.005285)[0m [0;1mSHOW FIELDS FROM datasets[0m [4;35;1mDataset Load (0.001132)[0m [0mSELECT * FROM datasets WHERE (datasets.`id` = 24) LIMIT 1[0m [4;36;1mDataitem Load (0.000646)[0m [0;1mSELECT * FROM dataitems WHERE (dataitems.dataset_id = 24) [0m
NameError (undefined local variable or method `dataset_hash' for Dataset:Class):
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1235:in `method_missing'
/app/models/dataset.rb:12:in `get_hash'
The funny thing is, it works exactly as it should when run through the console. Any help greatly appreciated.

Looks like you need to define the dataset_hash in your method. Something like this:
def self.get_hash(dataset_id)
dataset_hash = {}
#dataitems = Dataset.find_by_id(24).dataitems
#dataitems.each do |di|
dataset_hash[di.axis0value] = di.axis1value #assign value for each category value
end
return dataset_hash
end

Or you can just 'inject':
def self.get_hash(dataset_id)
Dataset.find_by_id(dataset_id).dataitems.inject({}) do |dataset_hash,di|
dataset_hash.merge(di.axis0value => di.axis1value)
end
end

Related

Rails benchmark reports less time than activerecord query

I'm trying to benchmark this query:
Person.where(age: 60)
When I run it in the console it says:
Person Load (1.2ms) SELECT "people".* FROM "people" WHERE "people"."age" = ? [["age", 60]]
When I benchmark it, it reports 0.17ms
def self.get_ages_sql
sixties = Person.where(age: 60)
end
Benchmark.bmbm do |x|
x.report('sql') {Person.get_ages_sql}
end
Whats the discrepency between:
0.17ms (benchmark)
vs
1.2ms (reported when I run command in console)
This code does not do database request actually:
Person.where(age: 60)
It just build ActiveRecord::Relation.
You can ensure by executing next code line by line in console and watch wich line actually produce DB request:
relation = Person.where(age: 60); 1
relation.class.name
relation.to_a
But Console misleads you with "Person Load ..." because it calls additional method like #inspect on each code line result. And this additional method causes DB request:
relation = Person.where(age: 60).inspect; 1
And that is why your benchmark is wrong - you do test of query creation not whole DB request. It should look like:
def self.get_ages_sql
Person.where(age: 60).to_a
end
Added: To get deep into Console, create
class ConsoleTest
def inspect
data.inspect
end
def data
'Doing DB request'
end
def self.test_data
ct = self.new
puts 'No request yet'
ct.data
end
end
and then try in Console:
ct = ConsoleTest.new
and
ct = ConsoleTest.new; 1
ct.data
and
ConsoleTest.test_data

Count Records within 30 days of today

I Have a model an Opportunity model that has an attribute called date_of_opportunity. I am trying to write a method that counts how many opportunities are within 30 days of today. However when I try to call my method in the console, I get the error 'undefined local variable or method'
Here is my model:
class Opportunity < ActiveRecord::Base
def calculate_num_days
num_days = 0
#opportunity = Opportunity.all
#opportunity.each do |opportunity|
if (opportunity.date_of_opportunity - Date.today < 30)
num_days = num_days + 1
return num_days
end
end
end
end
Can someone help me figure out whats wrong? Thanks!!
If you will get counts how many opportunities are within 30 days of today, you can try this :
class Opportunity < ActiveRecord::Base
def self.calculate_num_days(from = (Date.today-1.month).beginning_of_day,to = Date.today.end_of_day)
where(date_of_opportunity: from..to).count
end
end
And on your console you can type like this
Opportunity.calculate_num_days
Output looks like :
irb(main):001:0> Opportunity.calculate_num_days
←[0m←[1m←[35m (51.0ms)←[0m SELECT COUNT(*) FROM "opportunities" WHERE ("opportunities"."date_of_opportunity" BETWEEN '2014-05-04 00:00:00.000000' AND '2014-06-04 23:59:59.999999')
=> 2
You seem to want a class method, but are defining an instance method. Do this:
def self.calculate_num_days
...
end
Maybe, #opportunity = Opportunity.all should be #opportunities = Opportunity.all
Unless I am missing what you are trying to do I would let ActiveRecord do the heavy lifting. Opportunity.where("date_of_opportunity - :today < 30", today: Date.today).size
Disclaimer, this is completely untested

rails params[:user_id] return nil even they present

When i submit the form and rails console shows parameter passing as
Processing by RfpsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"OeKck54onJ6o72ABYvB6jMyBnU5X7BHY6NKH1sUtcHU=", "***rfp"=>{"user_id"=>"64***", "client_id"=>"3", "cms"=>"other2", "othercms"=>"dasda", "otherecommerce"=>"", "numberofpage"=>"", "designcomplexity"=>"", "browser"=>"","commit"=>"Create Rfp", "project_id"=>"18"}
in the controller when i check if params[:user_id].present? it always shows nil even though user_id is 64 as shown above
plz help me why does it happen
EDITS
Started GET "/projects/18/rfps/157" for 127.0.0.1 at 2014-04-23 10:16:24 +0530
Processing by RfpsController#show as HTML
Parameters: {"project_id"=>"18", "id"=>"157"}
Current user: anonymous
Completed 500 Internal Server Error in 7ms
NoMethodError (undefined method `[]' for nil:NilClass):
def show
#project = Project.find(params[:project_id])
#rfp = Rfp.find(params[:id])
# r = Rfp.find(params[:user_id])
# m = Rfp.find(params[:user_id])
if params[:rfp][:user_id].present?
#coo = User.where(:id => params[:rfp][:user_id]).first
end
end
in view i am jst printing name
Coordinator<%= #coo.firstname %>
Do this, here :user_id is under :rfp
if params[:rfp][:user_id].present?
Try this
if params['***rfp'][:user_id].present?
#coo = User.where(id: params['***rfp'][:user_id]).first
end
because params[:user_id] is not present.
params[:rfp][:user_id] is 64, however.
You have your user_id in rfp,by doing just params[:user_id] is not sufficient to get the value here.so it returns nil.
you have to do
params[:rfp][:user_id] #=> 64
to get the value of user_id.
So now by doing if params[:rfp]{:user_id].present? #=> true
will return true

error while setting up an existing Ruby On Rails project to local machine

I am setting up an existing 'Ruby On Rails' project to my local Machine after database setup terminal command 'rails server' executes successfully but when I hit localhost:3000 in browser I get following response....
Started GET "/" for 127.0.0.1 at 2014-04-08 16:07:01 +0530
Processing by ContentController#index as HTML
RvClass Load (0.1ms) SELECT "rv_classes".* FROM "rv_classes"
Testimonial Load (0.2ms) SELECT "testimonials".* FROM "testimonials" WHERE "testimonials"."approved" = 't'
Setting Load (0.2ms) SELECT "settings".* FROM "settings" LIMIT 1
Completed 500 Internal Server Error in 1136ms
NoMethodError (undefined method `features' for nil:NilClass):
app/controllers/content_controller.rb:18:in `index'
content_controller.rb:
class ContentController < ApplicationController
layout "application"
before_filter :check_for_mobile, :except => [:inventory, :disclaimer, :preowned, :sunridge_rv_video]
before_filter :prepare_for_mobile, :only => [:inventory, :social_media ]
def inventory
end
def social_media
end
def index
#tweets = begin
Twitter.user_timeline("sunridgeRV").slice(0, 6)
rescue Twitter::Error
[]
end
#feature_products = Setting.first.features.where("product_id is not null")
#home_page_testimonials = Testimonial.where(:approved=>true).shuffle.take(3)
#setting = Setting.first
#products = Product.where(special_on_homepage: true)
end
def disclaimer
render :partial => 'disclaimer'
end
def preowned
render :partial => 'used_guarantee'
end
def sunridge_rv_video
#rv_class_brands = RvClassBrand.has_video_link
end
def sunridge_team
#team_members = TeamMember.order("department_id").order("id")
end
def sales_home
#setting = Setting.first
end
end
the problem is this line :
#feature_products = Setting.first.features.where("product_id is not null")
here you call features method on Setting.first, and you get the error because Setting.first return nil (which means your settings table is empty for now), calling features method on Setting.first in this case is like calling : nil.features
some persons suggest you to fill in your database rows, but i think this is not really the way to solve this, any app should be working without any existing data
to solve the above bug you should just add a condition like this :
#feature_products = Setting.first.features.where("product_id is not null") unless Setting.first.nil?
or use try method :
#feature_products = Setting.first.try(:features).where("product_id is not null")
Hope this help

undefined method `each' in Rails 3.2

I've tried the same scenario in rails console
But why am I getting...
undefined method each for #<ProjectProcurementManagementPlan:0x007ff9ecda2148>
In my model, I have a callback that will update the form immediately
after_update :check_app_on_update?
def check_app_on_update?
self.each do |ppmp|
ppmp_year = ppmp.year
get_app = AnnualProcurementPlan.where(year: ppmp_year)
get_id = get_app.map{|a| a.id }
get_id.each do |app_id|
update_attribute(:annual_procurement_plan_id, app_id)
end
end
end
But keeps on getting undefined method 'each'
But whenever I remove the self.each loop...
I get 'stack level too deep' type of error.
Any workarounds will be appreciated.
EDIT
Okay, now i realize that I should stick to my old approach. And that is without each
def check_app_on_update?
ppmp_year = self.year
get_app = AnnualProcurementPlan.where(year: ppmp_year)
get_id = get_app.map{|a| a.id }
get_id.each do |app_id|
# ppmp = ProjectProcurementManagementPlan.last
# ppmp.update_attribute(:annual_procurement_plan_id, app_id )
#idd = app_id
end
update_attribute(:annual_procurement_plan_id, #idd )
end
But i am getting stack level too deep error
I saw from the logs, that there's an endless loop.
(0.5ms) UPDATE "project_procurement_management_plans" SET "status" = 'Approved', "updated_at" = '2013-05-31 09:55:00.000000', "annual_procurement_plan_id" = 1 WHERE "project_procurement_management_plans"."id" = 19
AnnualProcurementPlan Load (0.5ms) SELECT "annual_procurement_plans".* FROM "annual_procurement_plans" WHERE "annual_procurement_plans"."year" = 2012
(0.2ms) ROLLBACK
Completed 500 Internal Server Error in 16737ms
SystemStackError - stack level too deep:
(gem) actionpack-3.2.11/lib/action_dispatch/middleware/reloader.rb:70:in `'
My guess is:
stack level too deep occurs because update_attribute() calls check_app_on_update? again that calls update_attribute() that calls check_app_on_update? again ...
Need more information to be more confident ...
because self means 1 object and there is no .each method for 1 object, .each is for collections.

Resources