Rails database finding data by id - ruby-on-rails

SO this is probably going to get super confusing.
Basically i have a web application, The "Event" has an email where users can send out an email of their selected options.
So far the options save down to the database. the user id is saved in the table event_bookings, The id for this is linked into the package_bookings as event_id, This has a package ID which links to the package where i need the details from.
the TLDR is this
Table > Table >Table > Table that has the data i need
#event_booking.package_bookings.each
This currently shows everything inside the table with the packages id so basically i have access to the package id (in byebug) however i need to go and get the next level and show the package details
Any help would be lovely, I may have worded this super wrong!
Heres the little bit of byebug code that works
(byebug) #event_booking.package_bookings.first.id
PackageBooking Load (0.3ms) SELECT "package_bookings".* FROM "package_bookings" WHERE "package_bookings"."event_booking_id" = $1 ORDER BY "package_bookings"."id" ASC LIMIT 1 [["event_booking_id", 6]]
23
(byebug) #event_booking.package_bookings.first
CACHE (0.0ms) SELECT "package_bookings".* FROM "package_bookings" WHERE "package_bookings"."event_booking_id" = $1 ORDER BY "package_bookings"."id" ASC LIMIT 1 [["event_booking_id", 6]]
#<PackageBooking id: 23, package_id: 23, event_booking_id: 6, quantity_tickets: 1, created_at: "2015-11-19 08:55:06", updated_at: "2015-11-19 08:55:06", sub_options_selected: [27]>

As per your explanation you can find package detail like this:
#event_booking.package_bookings.each do |package_booking|
#package = package_booking.package ## You can find package detail like this
end
You can also add has_many :through Association in this case. Detail here.

Related

many cache calls in development log - how to prevent them

I have a Rails 4.2 app that has literally hundreds of calls like this:
CACHE (0.0ms) SELECT "albums".* FROM "albums" WHERE (albumable_type='ItemProfile' and albumable_id=33333) ORDER BY "albums"."id" ASC LIMIT 1
CACHE (0.0ms) SELECT COUNT(*) FROM "assets" WHERE "assets"."album_id" = $1 AND "assets"."is_enabled" = $2 [["album_id", 19182], ["is_enabled", true]]
CACHE (0.0ms) SELECT "albums".* FROM "albums" WHERE (albumable_type='ItemProfile' and albumable_id=33333) ORDER BY "albums"."id" ASC LIMIT 1
CACHE (0.0ms) SELECT "assets".* FROM "assets" WHERE "assets"."album_id" = $1 AND "assets"."is_enabled" = $2 ORDER BY "assets"."position" ASC LIMIT 1 [["album_id", 19182], ["is_enabled", true]]
Two questions:
Are these calls actually being made (my understanding is no due to "CACHE")?
Is there a way to tell Rails that it already has this info and doesn't need to check for it? Like hundreds of times seems liek a bug on my end
edit #1
so the problem is that there is stuff like the following:
def instore_image
album.enabled_assets.first
end
and
def image_600w
Rails.logger.info("#9797 here is instore_image_url")
instore_image.asset.url(:fixed_width600)
Rails.logger.info("#9898 here is instore_image_url")
end
The image_600w is calling a round of sql calls (whether cached or not). It seems like to prevent this from happening I need to set an instance variable on the object.
You should check out the section on Caching with Rails in Rails Guides:
1.5 SQL Caching
Query caching is a Rails feature that caches the result set returned
by each query so that if Rails encounters the same query again for
that request, it will use the cached result set as opposed to running
the query against the database again.
So these queries are actually being made by your application, however ActiveRecord intercepts these queries and prevents SQL query by directly delivering from Query cache.
Is there a way to tell Rails that it already has this info and doesn't need to check for it? Like hundreds of times seems liek a bug on my end.
Yes, Rails is already doing the best it can by reusing cached query results. You can use bullet to identify N+1 queries and other similar inefficient database usage patterns in your application.

Attribute not updated in production

Rails version: 4.2.3
I am into a strange situation here, I think it is a silly thing, but I dont know why this happens.
I receive a post notification on a URL, something like /accounts/payment. After process the json I received, I need do a update on a attribute of model Account. I am doing something like this:
account.update_columns(status: "delayed")
or update_attributes
everything works fine locally. All tests pass. But for a unknown reason when this code run in production, the attribute is not updated.
here some logs from production env.
SQL (1.7ms) UPDATE "accounts" SET "status" = 'delayed' WHERE "accounts"."type" IN ('StandardAccount') AND "accounts"."id" = $1 [["id", 94]]
Account.find(94).status
Account Load (0.7ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT 1 [["id", 94]]
=> "actived"
Thanks in advance
UPDATE 1
My modal schema is:
StandardAccount < Account
UPDATE 2
Not a Rails problem. I found a Trigger on DB involved with accounts table and cause the problem.

Rails console save not saving and is selecting from related table instead

When testing some things in the rails console I noticed this strange thing happening when I call a record and attempt to save it.
2.1.5 :026 > p = WorkOrder.first
WorkOrder Load (0.4ms) SELECT `work_orders`.* FROM `work_orders` ORDER BY `work_orders`.`id` ASC LIMIT 1
=> #<WorkOrder id: 3, client_id: 4, created_at: "2015-06-17 17:12:07", updated_at: "2015-06-17 17:12:07", dueDate: "2015-07-17", number: "0221506-003", project_type_id: 2, monthlySequenceNumber: "003", projectDescription: "Project", status_id: 1, labels_id: nil>
2.1.5 :027 > p.save
(0.2ms) BEGIN
ProjectType Load (0.5ms) SELECT `project_types`.* FROM `project_types` WHERE `project_types`.`id` = 2 LIMIT 1
(0.1ms) COMMIT
=> true
Why does it appear to be performing a select on the associated object? Also the records are not being committed back to the database. What am I missing that causes it to behave in such a seemingly strange way?
EDIT:
What prompted me to start try to save records that I pulled from the database was that I had an identical issue doing something like
p.delete
and then
p.save
which would return true, but would only perform that strange select on the Project Type
Why does it appear to be performing a select on the associated object?
This is possibly caused by validation code or callbacks in the WorkOrder model.
Also the records are not being committed back to the database. What am I missing that causes it to behave in such a seemingly strange way?
You have not modified the record, so the only field I would expect to be updated would be updated_at. It is possible to disable the timestamp feature for ActiveRecord. Have you done that? (reference Is there a way to avoid automatically updating Rails timestamp fields?)
UPDATE
The same thing happens when I tested p.delete followed by p.save, the result is true. This could be a bug, but I have not researched it enough to determine that yet.
After a quick look in the ActiveRecord source I think that what happens is that since you have first deleted your record (p), 0 rows in the database match that record's id (p.id). That means that when you run p.save 0 rows get updated (update instead of insert because the record is considered persisted). That number of rows gets compared with false here so that 0 != false returns true.
Due to the fact that you haven't changed any attribute, just try p.touch instead of p.save. This should save the record anyway.

Marshal not serializing or deserializing nested serialized attributes properly

This is kind of a tough problem to explain, because I don't really know what is going on. I've made a repository with instructions of how to reproduce:
https://github.com/bricker/cache_nested_serialized_attributes
Basically:
User has_many Posts
Post has serialized attribute :metadata
And to reproduce:
users = User.first(2)
users.first.posts.first
users.last.posts.first
dump = Marshal.dump(users)
Marshal.load(dump)
=> [#<User id: 1, name: "bricker", created_at: "2013-04-24 06:26:03", updated_at: "2013-04-24 06:26:03">,
:#new_record]
You can see the unexpected output in that final line. It only seems to occur under those specific conditions. Just calling users.first.posts works fine. Not calling .posts at all works fine. It's only when I load a specific post from a user before dumping that this happens.
The main difference I notice between Rails 4 (which works properly) and Rails 3.2.13 (which doesn't work) is that when calling Marshal.dump(users) in Rails 3, the Posts are reloaded:
dump = Marshal.dump(users)
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = 1
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = 2
... which doesn't happen in Rails 4.
I wish I could explain better but it's such an obscure problem. Please ask questions if you need clarification, and look at or clone the repo.
This is tested and confirmed on a vanilla Rails 3.2.13 (see repository). This behavior does not happen in Rails 4.
Thanks!
This issue is fixed on Rails master, and a simple patch is pending review on 3-2-stable. I've applied the patch manually in an initializer and it fixes the problem.
See here for the patch: https://github.com/rails/rails/issues/10322#issuecomment-16913855

Slow find with including multiple associations

In a Rails controller action I call
#grid = Grid.find(params[:id], :include => [:grid_properties, :grid_entities => [:entity => :properties]])
Unfortunately it takes really long. Benchmark.realtime (in development mode) tells me 1.8812830448150635, so about 2 seconds (Rails 3.0.7, Postgres 8.4).
When turning on the SQL logging I get the following for this line of code:
Grid Load (0.9ms) SELECT "grids".* FROM "grids" WHERE "grids"."id" = 2 LIMIT 1
GridProperty Load (2.5ms) SELECT "grid_properties".* FROM "grid_properties" WHERE ("grid_properties".grid_id = 2) ORDER BY row_order
GridEntity Load (1.3ms) SELECT "grid_entities".* FROM "grid_entities" WHERE ("grid_entities".grid_id = 2) ORDER BY row_order
Entity Load (3.0ms) SELECT "entities".* FROM "entities" WHERE ("entities"."id" IN (28,7,3,6,25,11,2,12))
Property Load (6.4ms) SELECT "properties".* FROM "properties" WHERE ("properties".entity_id IN (28,7,3,6,25,11,2,12))
Every database access seems to be in the low millisecond range. Why does it take so long in the end?
I guess that the time is spent on creating the object by Ruby. How many Properties are in that Grid? The time of 'SELECT FROM properties' looks relatively high.
You could further investigate the problem, if you have some functions where you could place checkpoints - logger.debug "CHECKPOINT: #{Time.now} #{caller(0).first}"
Do you have any 'on_load' callbacks, maybe?

Resources