18 Matching Annotations
  1. Jul 2022
    1. Create a new controller to override the original: app/controllers/active_storage/blobs_controller.rb

      Original comment:

      I've never seen monkey patching done quite like this.

      Usually you can't just "override" a class. You can only reopen it. You can't change its superclass. (If you needed to, you'd have to remove the old constant first.)

      Rails has already defined ActiveStorage::BlobsController!

      I believe the only reason this works:

      class ActiveStorage::BlobsController < ActiveStorage::BaseController

      is because it's reopening the existing class. We don't even need to specify the < Base class. (We can't change it, in any case.)

      They do the same thing here: - https://github.com/ackama/rails-template/pull/284/files#diff-2688f6f31a499b82cb87617d6643a0a5277dc14f35f15535fd27ef80a68da520

      Correction: I guess this doesn't actually monkey patch it. I guess it really does override the original from activestorage gem and prevent it from getting loaded. How does it do that? I'm guessing it's because activestorage relies on autoloading constants, and when the constant ActiveStorage::BlobsController is first encountered/referenced, autoloading looks in paths in a certain order, and finds the version in the app's app/controllers/active_storage/blobs_controller.rb before it ever gets a chance to look in the gem's paths for that same path/file.

      If instead of using autoloading, it had used require_relative (or even require?? but that might have still found the app-defined version earlier in the load path), then it would have loaded the model from activestorage first, and then (possibly) loaded the model from our app, which (probably) would have reopened it, as I originally commented.

    1. ActiveSupport.on_load :active_storage_blob do def accessible_to?(accessor) attachments.includes(:record).any? { |attachment| attachment.accessible_to?(accessor) } || attachments.none? end end ActiveSupport.on_load :active_storage_attachment do def accessible_to?(accessor) record.try(:accessible_to?, accessor) end end ActiveSupport.on_load :action_text_rich_text do def accessible_to?(accessor) record.try(:accessible_to?, accessor) end end module ActiveStorage::Authorize extend ActiveSupport::Concern included do before_action :require_authorization end private def require_authorization head :forbidden unless authorized? end def authorized? @blob.accessible_to?(Current.identity) end end Rails.application.config.to_prepare do ActiveStorage::Blobs::RedirectController.include ActiveStorage::Authorize ActiveStorage::Blobs::ProxyController.include ActiveStorage::Authorize ActiveStorage::Representations::RedirectController.include ActiveStorage::Authorize ActiveStorage::Representations::ProxyController.include ActiveStorage::Authorize end

      Interesting, rather clean approach, I think

  2. Aug 2021
  3. Jul 2021
    1. If you prefer monkeypatching (around 70) linguistics methods directly onto core classes, you can do that by adding a 'monkeypatch' option to ::use:
  4. Apr 2021
    1. Yes, you are right. That was a very bad workaround. Stubbing methods on NilClass can be compared to switching to dark side of force. Powerful but comes with a huge price. I highly don't recommend using my workaround from 1 year ago.
  5. Mar 2021
  6. Feb 2021
    1. According to this comment you might want to override the structurally_incompatible_values_for_or to overcome the issue: def structurally_incompatible_values_for_or(other) Relation::SINGLE_VALUE_METHODS.reject { |m| send("#{m}_value") == other.send("#{m}_value") } + (Relation::MULTI_VALUE_METHODS - [:eager_load, :references, :extending]).reject { |m| send("#{m}_values") == other.send("#{m}_values") } + (Relation::CLAUSE_METHODS - [:having, :where]).reject { |m| send("#{m}_clause") == other.send("#{m}_clause") } end
  7. Oct 2020
    1. There are other features you *could* actually polyfill, such as Array.of, Number.isNaN or Object.assign, because those don’t introduce syntax changes to the language – except that you shouldn’t.
    1. Polyfills are naughty as they patch native APIs, while ponyfills are pure and don't affect the environment.
    2. How are ponyfills better than polyfills? A polyfill is code that adds missing functionality by monkey patching an API. Unfortunately, it usually globally patches built-ins, which affects all code running in the environment. This is especially problematic when a polyfill is not fully spec compliant (which in some cases is impossible), as it could cause very hard to debug bugs and inconsistencies. Or when the spec for a new feature changes and your code depends on behavior that a module somewhere else in the dependency tree polyfills differently. In general, you should not modify API's you don't own.
  8. Jul 2020
  9. Mar 2020
    1. Instead of re-opening Ruby classes like that (I get involuntary twitches), for our little exercise we are going to invent another name

      IMHO, re-opening classes is okay. Certainly better than duplicating an entire core Ruby class and giving it a silly, less-meaningful name. (Though I'm not sure he actually intended people to use Lax instead of Lazy. I think he was just showing how easy it is to implement Lazy from scratch in Ruby.)

  10. Oct 2019