Rails pry-byebug not accessed - puts

I am trying to debug my code using the pry-byebug tool, but when I launch "rails console" in my terminal and then call on the class method in which the debugger should come into action, nothing happens. I have installed the gem and did a bundle install as per the documentation on:
https://github.com/deivid-rodriguez/pry-byebug
So basically I have 2 models, Grid and Cell. When a Grid instance is created I want to create the corresponding Cell instances. So far it doesn't work, but my main problem is that I am not able to debug and know where things go wrong.
I have therefore added the binding.pry command in the create method of the Grid class. Hoping to go through the rest of the code line by line and understand where I did something wrong.
However when in "rails console" I do something like Grid.new(session_id: 1, rows: 3, columns: 3), all I see is that the instance has been created and saved to the DB.
So I manage accessing the method "create" but not showing either the puts nor getting the pry-byebug options.
Even my logs don't show any error message.
I have read other posts on that subject but none have worked for me so far, such as this one:
Breakpoints with pry-byebug don't trigger in the console
Here is my GridController
require "pry-byebug"
class GridsController < ApplicationController
# after_create :generate_cells_for_grid
after_action :generate_cells_for_grid, only: [:create]
def new
#grid = Grid.new
end
def create
puts "In the CREATE method" # This puts never shows up in the console
binding.pry
#grid = Grid.new()
#grid.save
end
def generate_cells_for_grid
rows = #grid.rows
columns = #grid.columns
id = #grid.id
# Creating cells for every position to fill the grid
for row in 1..rows do
puts row
for column in 1..columns do
puts row
puts column
Cell.create({
grid_id: 1,
player_id: 1,
colour_id: 1,
x_coordonate: row,
y_coordonate: column,
alive: false
})
end
end
end
def index
end
def show
#grid = Grid.find(params[:id])
end
def update
#grid = Grid.find(params[:id])
#grid.update(params[:grid])
end
def edit
end
def delete
end
end
This is what I get in the "rails console":
[30] pry(main)> Grid.create(session_id: 1, rows: 3, columns: 3)
(1.7ms) BEGIN
Session Load (0.3ms) SELECT "sessions".* FROM "sessions" WHERE "sessions"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Grid Create (0.7ms) INSERT INTO "grids" ("session_id", "rows", "columns", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["session_id", 1], ["rows", 3], ["columns", 3], ["created_at", "2019-11-07 11:07:08.951668"], ["updated_at", "2019-11-07 11:07:08.951668"]]
(0.5ms) COMMIT
=> #<Grid:0x00007fce6b2cf790
id: 31,
session_id: 1,
rows: 3,
columns: 3,
created_at: Thu, 07 Nov 2019 11:07:08 UTC +00:00,
updated_at: Thu, 07 Nov 2019 11:07:08 UTC +00:00>
What am I doing wrong to not activate the pry-byebug? Is there a more efficient way to debug on Rails?
Thanks!

Related

How to access block parameters using Object.send

I'm trying to run the following code:
class RentLimit < ActiveRecord::Base
def self.load_data
rows = CSV.open("csvs/income_limits_2011_to_2015.csv").read
rows.shift
rows.each do |county, yr, date, _50pct_1br, _50pct_2br, _50pct_3br, _50pct_4br, _60pct_1br, _60pct_2br, _60pct_3br, _60pct_4br|
[50, 60].each do |ami|
[1, 2, 3, 4].each do |br|
r = new
r.county = county
r.state = "SC"
r.year = yr
r.effective_date = Date.parse(date)
r.pct_ami = ami
r.br = br
r.max_rent = self.send("_#{ami}pct_#{br}br".to_sym)
r.save
end#of brs
end# of amis
end# of rows
end
end
but am getting this error message when trying to run it:
NoMethodError: undefined method `_50pct_1br' for #<Class:0x007fe942ce3b18>
The send method isn't able to access those block parameters inside of the scope. Is there any way to give access to block parameters to send? If not, how else might I dynamically access block parameters?
How do I use send or its equivalent to access block parameters in Ruby?
This is much easier if you tell CSV.open what your column names are. It looks like your CSV file might have a header row that you're skipping with rows.shift, in which case you shouldn't skip it, and use the headers: true option. Then you can access each field by name with row["field_name"] or, in your case, row["_#{ami}pct_#{br}br"]:
CSV_PATH = "csvs/income_limits_2011_to_2015.csv"
DEFAULT_STATE = "SC"
def self.load_data
CSV.open(CSV_PATH, 'r', headers: true) do |csv|
csv.each do |row|
max_rent = row["_#{ami}pct_#{br}br"]
create(
county: row["county"],
state: DEFAULT_STATE,
year: row["yr"],
effective_date: Date.parse(row["date"]),
pct_ami: ami,
br: br,
max_rent: max_rent,
)
end
end
end
Note that I used CSV.open with a block to ensure that the file is closed after it's been read, which your original code wasn't doing. I also used create instead of new; ... save, since the latter is needlessly verbose.
If you're skipping the first row for some other reason, or you want to use field names other than those in the header row, you can set the options return_headers: false, headers: names, where names is an array of names, e.g.:
CSV_HEADERS = %w[
county yr date _50pct_1br _50pct_2br _50pct_3br _50pct_4br
_60pct_1br _60pct_2br _60pct_3br _60pct_4br
].freeze
def self.load_data
CSV.open(CSV_PATH, 'r', return_headers: false, headers: CSV_HEADERS) do |csv|
# ...
end
end
Finally, since some of your attributes are the same for every object created, I'd move those out of the loop:
def self.load_data
base_attrs = { state: DEFAULT_STATE, pct_ami: ami, br: br }
CSV.open(CSV_PATH, 'r', headers: true) do |csv|
csv.each do |row|
create(base_attrs.merge(
county: row["county"],
year: row["yr"],
effective_date: row["date"],
max_rent: row["_#{ami}pct_#{br}br"]
))
end
end
end

Rails 4.0.3: after_save callback seems to be called too soon?

Given the following two classes Customer and Order, I have a problem which I have narrowed down to the execution times of the callbacks I am using.
The reason for the use of callbacks is that I need to store the aggregated diff of each customer without having to iterate through all of his/her orders each time. So I realized that it might be a good approach to use callbacks to first update the diff on each individual order before each save, and second, update the aggregated diff on the customer model after each order is saved.
The symptoms I get are weird seemingly random errors where it tells me that the diff between two orders which both totals $238 is $15. When I limited the debugger to the affected customers I realized that it was simply skipping the orders.each loop below (but only in some cases) because there were no orders associated to the customer.
Since all Customers have at least one order and the order is actually created before the customer in this system, that can't be true.
Is there some way I can enforce that the after_save callback is indeed not called until ActiveRecord has finished both saving the Order object and updating the relation to the Customer model?
As you can see I also tried to use a timer to see if I could get to work by sleeping the thread for a short while before continuing, but that did not work.
class Customer < ActiveRecord::Base
...
has_many :orders
before_save :calculate_shipping
def update_total_diff
sum = 0
orders.each do |o|
if o.diff.present?
sum += o.diff
end
end
# HERE IS THE PROBLEM: When inspecting the orders collection in the debuggger it is empty.
# Make sure shipping is updated
calculate_shipping
# Since we are calculating the diff shipping must be subtracted
sum -= shipping
self.total_diff = sum
self.save
end
...
private
def calculate_shipping
...returns either 15 or 0
end
end
And the Order model:
class Order < ActiveRecord::Base
...
belongs_to :customer
before_save :update_diff
after_save :update_customer
private
def update_diff
#Updates a local value
......
end
def update_customer
#Here we trigger a function on the customer model in order to tell it that it needs to re-calculate
sleep(1/10) #Tried this to test - no luck
if self.customer_id.present? && diff.present?
self.customer.update_total_diff
end
end
end
Edit:
Have a look at this:
From: /vagrant/app/models/order.rb # line 23 Order#update_customer:
21: def update_customer
22: if self.customer_id.present?
=> 23: binding.pry
24: end
25: if self.customer_id.present? && diff.present?
26: self.customer.update_total_diff
27: end
28: end
...
[4] pry(#<Order>)> michael = self.customer
=> #<Customer id: 2, name: "Michael xxx", mail: "xxx#gmail.com", shipping_address_id: 2, created_at: "2014-07-17 11:00:12", updated_at: "2014-07-17 11:00:12", shipping: #<BigDecimal:7fada4e707d0,'0.0',9(36)>, total_diff: nil>
[5] pry(#<Order>)> michael.orders
=> []
[6] pry(#<Order>)> michael = Customer.find(2)
=> #<Customer id: 2, name: "Michael xxx", mail: "xxx#gmail.com", shipping_address_id: 2, created_at: "2014-07-17 11:00:12", updated_at: "2014-07-17 11:00:12", shipping: #<BigDecimal:7fada5008098,'0.0',9(36)>, total_diff: nil>
[7] pry(#<Order>)> michael.orders
=> [#<Order id: 2, pledge_id: 4808304, amount: #<BigDecimal:7fada50fc120,'0.89E2',9(36)>, customer_id: 2, perk_id: 9, created_at: "2013-11-23 00:00:00", updated_at: "2014-07-17 11:00:12", diff: #<BigDecimal:7fada5108240,'0.0',9(36)>>]
[8] pry(#<Order>)>
I tried stopping my debugger right before the Order tells Customer to re-calculate. I tried assigning the same customer twice to the variable "michael". If I assign the variable simply with:
michael = self.customer
The object won't know about any of its associated orders. If I assign it thorugh activerecord like so:
michael = Customer.find(2)
It will work. Why is that?
For now I managed to fix it by doing this, but I'd still like to know if anyone can explain the situation for me?
me = Customer.find(id)
me.orders.each do |o|
if o.diff.present?
sum += o.diff
end
end

cassandra Ruby : multiple values for a block parameter (2 for 1)

I am trying to follow a tutorial on big data, it wants to reads data from a keyspace defined with cqlsh.
I have compiled this piece of code successfully:
require 'rubygems'
require 'cassandra'
db = Cassandra.new('big_data', '127.0.0.1:9160')
# get a specific user's tags
row = db.get(:user_tags,"paul")
###
def tag_counts_from_row(row)
tags = {}
row.each_pair do |pair|
column, tag_count = pair
#tag_name = column.parts.first
tag_name = column
tags[tag_name] = tag_count
end
tags
end
###
# insert a new user
db.add(:user_tags, "todd", 3, "postgres")
db.add(:user_tags, "lili", 4, "win")
tags = tag_counts_from_row(row)
puts "paul - #{tags.inspect}"
but when I write this part to output everyone's tags I get an error.
user_ids = []
db.get_range(:user_tags, :batch_size => 10000) do |id|
# user_ids << id
end
rows_with_ids = db.multi_get(:user_tags, user_ids)
rows_with_ids.each do |row_with_id|
name, row = row_with_id
tags = tag_counts_from_row(row)
puts "#{name} - #{tags.inspect}"
end
the Error is:
line 33: warning: multiple values for a block parameter (2 for 1)
I think the error may have came from incompatible versions of Cassandra and Ruby. How to fix it?
Its a little hard to tell which line is 33, but it looks like the problem is that get_range yields two values, but your block is only taking the first one. If you only care about the row keys and not the columns then you should use get_range_keys.
It looks like you do in fact care about the column values because you fetch them out again using db.multi_get. This is an unnecessary additional query. You can update your code to something like:
db.get_range(:user_tags, :batch_size => 10000) do |id, columns|
tags = tag_counts_from_row(columns)
puts "#{id} - #{tags.inspect}"
end

ActiveRecord::MultiparameterAssignmentErrors

I am new to rails 4 . I am using time_select to display time in my views.
While creating new event object I am getting error like:
ActiveRecord::MultiparameterAssignmentErrors (1 error(s) on assignment of
multiparameter attributes [error on assignment [12, 15] to time_begin
(Missing Parameter - time_begin(1))]):
In views:
<%= f.time_select :time_begin, :ampm => true, include_blank: true, :disabled => true %>
In my controller:
I have tried like this way:
params = event_params
hours = params['time_begin(4i)']
minutes = params['time_begin(5i)']
date = Date.strptime(params[:event_start], "%Y-%m-%d")
date = DateTime.civil(date.year,date.month, date.day, hours.to_i, minutes.to_i, 0, 0)
params[:time_begin] = date
#event = Event.new(params)
private
def event_params
params.require(:event).permit(:time_begin)
end
You need to modify your database field to be of type time not date_time. The following migration should do:
def up
change_column :events, :time_begin, :time
end
def down
change_column :events, :time_begin, :datetime
end
Note, that both types are stored same way in the database, the difference is that rails will purge (or rather reassign) its date part when you specify column to be a time. This unfortunately means that you will be able to call start_time.day, but the returned value will have no true meaning (always one), which might be a little misleading.

search an array and do a specific task based on if a value is found

Ok let me ask this another way. This is an example of an inciident table I'm going to import in a csv format.
id:
incident_datetime: 2012-09-24 08:07:00.000000+0000
location: Hamburg
report_nr: 33-11-00201
responsible_party: John
area_resident: No
street: 6108 FoxHunt
city: Lexington
state: Ky
home_phone: 111-111-1111
cell_phone: 222-222-2222
insurance_carrier_name: Nationwide
insurance_carrier_street: Waller
insurance_carrier_city: Lexington
insurance_carrier_state: KY
insurance_carrier_phone: 666-666-6666
insurance_carrier_contact: Jason
policy_nr: 2sdf2sdf
vin_nr: ZTZHK3fhr5546107407
license_nr: 520-VDH
vehicle_make: Toyota
vehicle_model: Tacoma
vehicle_year: 2004
created_at:
updated_at:
status: Recieved
user_id: 16
resp_zip: 40509
insur_zip: 40509
And here is the code for the rakefile.
require 'csv'
namespace :import_incidents_csv do
task :create_incidents => :environment do
puts "Import Incidents"
csv_text = File.read('c:/rails/thumb/costrecovery_csv/lib/csv_import/incidents.csv')
csv = CSV.parse(csv_text, :headers => true)
#incident_id_array = []
csv.each do |row|
row = row.to_hash.with_indifferent_access
Incident.create!(row.to_hash.symbolize_keys)
#incident_id_array << Incident.last.id
end
end
end
The id at the top will automatically get assigned a value when it gets dumped into the database. I'm then taking that id value and saving it in an array and creating a timesheet for it. This is what the timesheet looks like.
id:
name:
date:
incident_id: x
created_at:
updated_at:
The timesheet needs to be created because a bunch of models "belong to it". And here is the rakefile to create this:
require 'csv'
namespace :import_timesheets_csv do
task :create_timesheets => :environment do
puts "Import Timesheets"
csv_text = File.read('c:/rails/thumb/costrecovery_csv/lib/csv_import/timesheets.csv')
csv = CSV.parse(csv_text, :headers => true)
#timesheet_id_array = []
csv.each_with_index do |row,index|
row = row.to_hash.with_indifferent_access
Timesheet.create!(row.to_hash.symbolize_keys)
#timesheet_id_array << Timesheet.last.id
timesheet = Timesheet.last
timesheet.incident_id = #incident_id_array[index]
timesheet.save
end
end
end
So at this point, I've created a new incident, and it's linked to a new timesheet I just created. Now I want to import a csv file creating safety_officers. Here is what the file would look like.
id:
name: Safety Officer 1
first_hour: 1
additional_hours: 2
total_hours: 3
hazmat_hours: 0.5
rate1:
rate2:
timesheet_id:
created_at:
updated_at:
And here is the code for the Importing the safety_officer.csv file.
require 'csv'
namespace :import_safety_officers_csv do
task :create_safety_officers => :environment do
puts "Import Safety Officers"
csv_text = File.read('c:/rails/thumb/costrecovery_csv/lib/csv_import/safety_officers.csv')
csv = CSV.parse(csv_text, :headers => true)
csv.each_with_index do |row,index|
row = row.to_hash.with_indifferent_access
SafetyOfficer.create!(row.to_hash.symbolize_keys)
safety_officer = SafetyOfficer.last
safety_officer.timesheet_id = #timesheet_id_array[index]
safety_officer.save
end
end
end
So above is an example of 1 incident report being imported, 1 timesheet being imported/created and 1 safety officer being imported. I'm trying to figure out how my code needs to be modified so the safety officers know which incident report they belong to. How do I assign them the proper timesheet_id that corresponds to their incident. I have several other models that I have to do this with as well but i just need to get it figured out for one of them and then I can duplicate it for the rest. And all of these are saved as different rake files and are executed by one master rake task which looks like this.
require 'csv'
namespace :combine_csv do
task :combine => :environment do
Rake::Task["import_incidents_csv:create_incidents"].invoke
Rake::Task["import_timesheets_csv:create_timesheets"].invoke
Rake::Task["import_safety_officers_csv:create_safety_officers"].invoke
end
end

Resources