Faker object doesn't always seem to be populated when generating models from factories - ember-cli-mirage

https://ember-twiddle.com/e9d2be366d42ef411edc87c04825fa56?openFiles=mirage.factories.user.js%2C
why doesn't faker.image.imageURL() work here? (open debug to see it falling over of course). This isn't the only one of these I've seen periodically fail. Sometimes when I set a breakpoint in my mirage setup and inspect the faker object these things will be defined and sometimes they're not.

I believe it's just a typo, you're typing imageURL instead of imageUrl.

Related

How can I verify that an ActiveStorage blob is actually present?

I've got an application that's been running in production for many months now, with tens of thousands of attachments. This morning, I tried to do an operation on one of these attachments, and got the following error:
Azure::Core::Http::HTTPError: BlobNotFound (404): The specified blob does not exist.
I can easily recreate this blob, but this situation makes me want to write a script to check the integrity of all of my attachments, and verify that no others have gone missing. (I expect that this was a transitory network error, and I expect to find very few, but I need the peace of mind.)
I can see that there is a method to call that seems to do exactly what I need: exist?(key), which is documented here:
https://github.com/rails/rails/blob/master/activestorage/lib/active_storage/service/disk_service.rb
However, I can't figure out how I'm supposed to call it. According to this, it's implemented as an instance method. So how do I reference my Rails application's active ActiveStorage instance (depending on environment) to use this method?
I wondered if it were possible to backtrack to get the instance of ActiveStorage::Service::AzureStorageService (in production), and found this answer on finding each instance of a class.
From there, I found that I could:
asass = ObjectSpace.each_object(ActiveStorage::Service::AzureStorageService).first
Which then allowed me to:
2.5.5 :015 > asass.exist?(c.json.blob.key)
AzureStorage Storage (313.3ms) Checked if file exists at key: ....PTLWNbEFLgeB8Y5x.... (yes)
=> true
Further digging around in the bowels of Rails' GitHub issues led me to see that the reference to the ActiveStorage service instance can be reached through an instance of a stored object, and that I could always be using the send() method to call one of its methods:
2.5.5 :045 > c.json.blob.service.send(:exist?, c.json.blob.key)
AzureStorage Storage (372.4ms) Checked if file exists at key: ....PTLWNbEFLgeB8Y5x.... (yes)
=> true
I'm sure both approaches are lighting up the same code paths, but I'm not sure which one I prefer at the moment. I still think there must exist some way to traverse the Rails instance through app. or Rails.application. to get to the ActiveStorage instance, but I haven't been able to suss that out.

Updating a Rails model's attributes through mongoid using normal persistence methods

I have been chasing an issue down for a while now, and still cannot figure out what's happening. I am unable to edit documents made from my gem through normal persistence methods, like update or even just editing attributes and calling save.
For example, calling:
Scram::Policy.where(id: a.id).first.update!(priority: 12345)
Will not work at all (there are no errors, but the document has not updated). But the following will work fine:
Scram::Policy.collection.find( { "_id" => a.id } ).update_one( { "$set" => {"priority" => 12345}})
I am not sure what I'm doing wrong. Calling update and save on any other model works fine. The document in question is from my gem: https://github.com/skreem/scram/blob/master/lib/scram/app/models/policy.rb
I cannot edit its embedded documents either (targets). I have tried removing the store_in macro, and specifying exactly what class to use using inverse_of and class_name in a fake app to reimplement these classes: https://github.com/skreem/scram-implementation/blob/master/lib/scram/lib/scram/app/models/policy.rb
I've tried reimplementing the entire gem into a clean fake rails application: https://github.com/skreem/scram-implementation
Running these in rails console demonstrates how updating does not work:
https://gist.github.com/skreem/c70f9ddcc269e78015dd31c92917fafa
Is this an issue with mongoid concerning embedded documents, or is there some small intricacy I am missing in my code?
EDIT:
The issue continues if you run irb from the root of my gem (scram) and then run the following:
require "scram.rb"
Mongoid.load!('./spec/config/mongoid.yml', :test)
Scram::Policy.first.update!(priority: 32) #=> doesn't update the document at all
Scram::Policy.where(id: "58af256f366a3536f0d54a61").update(priority: 322) #=> works just fine
Oddly enough, the following doesn't work:
Scram::Policy.where(id: "58af256f366a3536f0d54a61").first.update(priority: 322)
It seems like first isn't retrieving what I want. Doing an equality comparison shows that the first document is equal to the first returned by the where query.
Well. As it turns out, you cannot call a field collection_name or else mongoid will ensure bad things happen to you. Just renaming the field solved all my issues. Here's the code within mongoid that was responsible for the collision: https://github.com/mongodb/mongoid/blob/master/lib/mongoid/persistence_context.rb#L82
Here's the commit within my gem that fixed my issue: https://github.com/skreem/scram/commit/25995e955c235b24ac86d389dca59996fc60d822
Edit:
Make sure to update your Mongoid version if you have dealt with this issue and did not get any warnings! After creating an issue on the mongoid issue tracker, PersistenceContext was added to a list of prohibited methods. Now, attempting to use collection_name or collection as a field will cause mongoid to spit out a couple of warnings.
Fix commit: https://github.com/mongodb/mongoid/commit/6831518193321d2cb1642512432a19ec91f4b56d

Rails vs Ruby namespacing rules.

Reading this really good article on Rails namespacing and module lookup. Here
I don't understand what this means:
If constants are loaded only when they’re first encountered at
runtime, then by necessity their load order depends on the individual
execution path.
What is the individual execution path?
I think that non-understand leads me to not understand this:
As soon as an already-loaded constant Baz is encountered, Rails knows
this cannot be the Baz it is looking for, and the algorithm raises a
NameError.
or more importantly this:
The first time, as before, is down to the loss of nesting information.
Rails can’t know that Foo::Qux isn’t what we’re after, so once it
realises that Foo::Bar::Qux does not exist, it happily loads it.
The second time, however, Foo::Qux is already loaded. So our reference can’t have been to that constant, otherwise Ruby would have
resolved it, and autoloading would never have been invoked. So the
lookup terminates with a NameError, even though our reference could
(and should) have resolved to the as-yet-unloaded ::Qux.
Why doesn't rails use the constant that is encountered that is already loaded? Also why does running:
Foo::Bar.print_qux
twice lead to two different outcomes?
By "execution path" they mean the way your code is running. If there's a reference to a class X::Y inside an if block that isn't executed, that means your execution path bypasses it so it's not loaded.
This is different than force-loading all classes referenced in your code at parse time. They're simply loaded as they're exercised if and only if that given line of code is executed.
The autoloader has a strategy for trying to load modules starting with the most specific and then looking for increasingly global names. Qux is tested against the current module context, then the root of that and so on. This is how symbols are resolved.
In that example the auto-loaded version actually pushes the Foo::Qux definition ahead of ::Qux in terms of priority. That's the major change there.

Undefined Method errors on basic AR and AS methods when running threaded with Sidekiq on Heroku

I am getting a couple different errors at a particular line of code in one of my models when running in Sidekiq-queued jobs. The code in question is:
#lookup_fields[:asin] ||= self.book_lookups.find_by_name("asin").try(:value)
I either get undefined method 'scope' for #<ActiveRecord::Associations::AssociationScope:0x00000005f20cb0> or undefined method 'aliased_table_for' for #<ActiveRecord::Associations::AliasTracker:0x00000005bc3f90>.
At another line of code in another Sidekiq job, I get the error undefined method 'decrypt_and_verify' for #<ActiveSupport::MessageEncryptor:0x00000007143208>.
All of these errors make no sense, as they are standard methods of the Rails runtime support libraries.
The model in question has a :has_many association defined for the "book_lookups" model, "name" and "value" are fields in the "book_lookups" model. This always happens on the first 1-3 records processed. If I run the same code outside of a Sidekiq job, these errors do not occur.
I cannot reproduce the error on my development machine, only on production which is hosted at Heroku.
I may have "solved" the first set of errors by putting the code `BookLookup.new()' in an initializer, forcing the model to load before Sidekiq creates any threads. Only one night's work to go on, so we'll have to see if the trend continues...
Even if this solves the immediate problem, I don't think it solves the real underlying issue, which is classes not getting fully loaded before being used. Is class-loading an atomic operation? Is it possible for one thread to start loading a class and another to start using the class before it is fully loaded?
I believe that I have discovered the answer: config.threadsafe!, which I had not done. I have now done that and most if not all of the errors have disappeared. References: http://guides.rubyonrails.org/configuring.html, http://m.onkey.org/thread-safety-for-your-rails (especially the section "Ruby's require is not atomic").

Rails: "Stack level too deep" error when calling "id" primary key method

This is a repost on another issue, better isolated this time.
In my environment.rb file I changed this line:
config.time_zone = 'UTC'
to this line:
config.active_record.default_timezone = :utc
Ever since, this call:
Category.find(1).subcategories.map(&:id)
Fails on "Stack level too deep" error after the second time it is run in the development environment when config.cache_classes = false. If config.cache_classes = true, the problem does not occur.
The error is a result of the following code in active_record/attribute_methods.rb around line 252:
def method_missing(method_id, *args, &block)
...
if self.class.primary_key.to_s == method_name
id
....
The call to the "id" function re-calls method_missing and there is nothing that prevents the id to be called over and over again, resulting in stack level too deep.
I'm using Rails 2.3.8.
The Category model has_many :subcategories.
The call fails on variants of that line above (e.g. Category.first.subcategory_ids, use of "each" instead of "map", etc.).
Any thoughts will be highly appreciated.
Thanks!
Amit
Even though this is solved, I just wanted to chime in on this, and report how I fixed this issue. I had the same symptoms as the OP, initial request .id() worked fine, subsequent requests .id() would throw an the "stack too deep" error message. It's a weird error, as it generally it means you have an infinite loop somewhere. I fixed this by changing:
config.action_controller.perform_caching = true
config.cache_classes = false
to
config.action_controller.perform_caching = true
config.cache_classes = true
in environments/production.rb.
UPDATE: The root cause of this issue turned out to be the cache_store. The default MemoryStore will not preserve ActiveRecord models. This is a pretty old bug, and fairly severe, I'm not sure why it hasn't been fixed. Anyways, the workaround is to use a different cache_store. Try using this, in your config/environments/development.rb:
config.cache_store = :file_store
UPDATE #2: C. Bedard posted this analysis of the issue. Seems to sum it up nicely.
Having encountered this problem myself (and being stuck on it repeateadly) I have investigated the error (and hopefully found a good fix). Here's what I know about it:
It happens when ActiveRecord::Base#reset_subclasses is called by the dispatcher between requests (in dev mode only).
ActiveRecord::Base#reset_subclasses wipes out the inheritable_attributes Hash (where #skip_time_zone_conversion_for_attributes is stored).
It will not only happen on objects persisted through requests, as the "monkey test app" from #1290 shows, but also when trying to access generated association methods on AR, even for objects that live only on the current request.
This bug was introduced by this commit where the #skip_time_zone_conversion_for_attributes declaration was changed from base.cattr_accessor to base.class_inheritable_accessor. But then again, that same commit also fixed something else.
The patch initially submitted here that simply avoids clearing the instance_variables and instance_methods in reset_subclasses does introduce massive leaking, and the amounts leaked seem directly proportional to complexity of the app (i.e. number of models, associations and attributes on each of them). I have a pretty complex app which leaks nearly 1Mb on each request in dev mode when the patch is applied. So it's not viable (for me anyways).
While trying out different ways to solve this, I have corrected the initial error (skip_time_zone_conversion_for_attributes being nil on 2nd request), but it uncovered another error (which just didn't happen because the first exception would be raised before getting to it). That error seems to be the one reported in #774 (Stack overflow in method_missing for the 'id' method).
Now, for the solution, my patch (attached) does the following:
It adds wrapper methods for #skip_time_zone_conversion_for_attributes methods, making sure it always reads/writes the value as an class_inheritable_attribute. This way, nil is never returned anymore.
It ensures that the 'id' method is not wiped out when reset_subclasses is called. AR is kinda strange on that one, because it first defines it directly in the source, but redefines itself with #define_read_method when it is first called. And that is precisely what makes it fail after reloading (since reset_subclasses then wipes it out).
I also added a test in reload_models_test.rb, which calls reset_subclasses to try and simulate reloading between requests in dev mode. What I cannot tell at this point is if it really triggers the reloading mechanism as it does on a live dispatcher request cycle. I also tested from script/server and the error was gone.
Sorry for the long paste, it sucks that the rails lighthouse project is private. The patch mentioned above is private.
-- This answer is copied from my original post here.
Finally solved!
After posting a third question and with help of trptcolin, I could confirm a working solution.
The problem: I was using require to include models from within Table-less models (classes that are in app/models but do not extend ActiveRecord::Base). For example, I had a class FilterCategory that performed require 'category'. This messed up with Rails' class caching.
I had to use require in the first place since lines such as Category.find :all failed.
The solution (credit goes to trptcolin): replace Category.find :all with ::Category.find :all. This works without the need to explicitly require any model, and therefore doesn't cause any class caching problems.
The "stack too deep" problem also goes away when using config.active_record.default_timezone = :utc

Resources