PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label monkeypatching. Show all posts
Showing posts with label monkeypatching. Show all posts

Saturday, November 26, 2022

[FIXED] Why is "include" not using my monkey-pathced method for my module?

 November 26, 2022     module, monkeypatching, ruby-on-rails, ruby-on-rails-6     No comments   

Issue

I’m using Ruby on Rails 6.1.4.4. I want to override a method in a gem, whose signature is this

module Juixe
  module Acts
    module Commentable
      module ClassMethods
        def acts_as_commentable(*args)
        …
       end
      end
    end
  end
end

So I tried creating a file, lib/ext/acts_as_commentable_extensions.rb, and including this code

require 'acts_as_commentable'

module GemExtensions
  module Commentable
    def hello
      print "hello\n"
    end

    def acts_as_commentable(*args)
      abcdef
    end
  end
end

module Juixe
  module Acts
    module Commentable
      module ClassMethods
        include GemExtensions::Commentable
      end
    end
  end
end

Juixe::Acts::Commentable::ClassMethods.instance_method(:hello).source.display
Juixe::Acts::Commentable::ClassMethods.instance_method(:acts_as_commentable).source.display

Although the first statement prints out the correct source code from my new method “hello,” the second prints out the old source code from the original gem as opposed to my new code. How do I override this method with my own code?


Solution

Try prepend GemExtensions::Commentable instead of include, it will make Ruby to search for the method first in prepended module. More explanation here https://medium.com/@leo_hetsch/ruby-modules-include-vs-prepend-vs-extend-f09837a5b073



Answered By - stolarz
Answer Checked By - Marie Seifert (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Saturday, November 5, 2022

[FIXED] Why use monkeypatch.setenv instead of os.putenv

 November 05, 2022     environment-variables, monkeypatching, pytest, python     No comments   

Issue

pytest's monkeypatch module provides a setenv function which will Set environment variable name to value. Why does monkeypatch provide this? It sounds the same as os.putenv? It provides prepend argument as a convenience, but that seems like a weak reason to have a new function for setting an environment variable.


Solution

This is about tearing down the changes that the test makes in the environment. If you only use os.putenv, or modify the os.environ directly, then your modifications will stay in place even after the end of the test. That means the next test that runs will have the change applied, too! Since the tests are not necessarily ordered, it means you no longer have a repeatable and reliable test execution.

It's undesirable for a individual tests to change some global mutable state, therefore either use a context manager or the fixture provided when you need to configure environment variables during tests.



Answered By - wim
Answer Checked By - David Goodson (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Tuesday, September 6, 2022

[FIXED] How can I modify the XMLHttpRequest responsetext received by another function?

 September 06, 2022     ajax, javascript, monkeypatching, xmlhttprequest     No comments   

Issue

I am trying to modify the responseText received by a function that I cannot modify. This function creates a XMLHttpRequest that I can attach to, but I have been unable to "wrap" the responseText in a way that allows me to modify the content before the original function receives it.

Here's the full original function:

function Mj(a, b, c, d, e) {
    function k() {
        4 == (m && 'readyState' in m ? m.readyState : 0) && b && ff(b) (m)
    }
    var m = new XMLHttpRequest;
    'onloadend' in m ? m.addEventListener('loadend', k, !1)  : m.onreadystatechange = k;
    c = ('GET').toUpperCase();
    d = d || '';
    m.open(c, a, !0);
    m.send(d);
    return m
}
function ff(a) {
    return a && window ? function () {
        try {
            return a.apply(this, arguments)
        } catch(b) {
            throw jf(b),
                b;
        }
    } : a
}

I have also tried to manipulate the reiceiving function k(); in an attempt to reach my goal, but since it doesn't depend on any data passing to the function (for example k(a.responseText);) I had no success.

Is there any way that I can achieve this? I do not wish to use js libraries (such as jQuery);


EDIT: I understand that I cannot change .responseText directly since it is read-only, but I am trying to find a way to change the content between the response and receiving function.


EDIT2: Added below one of the methods I have tried to intercept and change .responseText which has been addapted from here: Monkey patch XMLHTTPRequest.onreadystatechange

(function (open) {
XMLHttpRequest.prototype.open = function (method, url, async, user, pass) {
    if(/results/.test(url)) {
      console.log(this.onreadystatechange);
        this.addEventListener("readystatechange", function () {
            console.log('readystate: ' + this.readyState);
            if(this.responseText !== '') {
                this.responseText = this.responseText.split('&')[0];
            }
        }, false);
    }
    open.call(this, method, url, async, user, pass);
};
})(XMLHttpRequest.prototype.open);

EDIT3: I forgot to include that the functions Mj and ff are not globally available, they are both contained inside an anonymous function (function(){functions are here})();


EDIT4: I have changed the accepted answer because AmmarCSE's does not have any of the problems and complexity linked to jfriend00's answer.

The best answer explained in short is as follows:

Listen to whichever request you want to modify (make sure your listener will intercept it before the original function destination does, otherwise there is no point in modifying it after the response has already been used).

Save the original response (if you want to modify it) in a temporary variable

Change the property you want to modify to "writable: true", it will erase whichever value it had. In my case I use

Object.defineProperty(event, 'responseText', {
    writable: true
});

Where event is the object returned by listening to the load or readystatechange event of the xhr request

Now you can set anything you want for your response, if all you wanted was to modify the original response then you can use that data from your temporary variable and then save the modifications in the response.


Solution

One very simple workaround is to change the property descriptor for responseText itself

Object.defineProperty(wrapped, 'responseText', {
     writable: true
});

So, you can extend XMLHttpRequest like

(function(proxied) {
    XMLHttpRequest = function() {
        //cannot use apply directly since we want a 'new' version
        var wrapped = new(Function.prototype.bind.apply(proxied, arguments));

        Object.defineProperty(wrapped, 'responseText', {
            writable: true
        });

        return wrapped;
    };
})(XMLHttpRequest);

Demo



Answered By - AmmarCSE
Answer Checked By - Katrina (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing