So I have a Rails 3.0 Engine (gem).
It provides a controller at app/controllers/advanced_controller.rb, and a corresonding helper at app/helpers/advanced_helper.rb. (And some views of course).
So far so good, the controller/helper/views are just automatically available in the application using the gem, great.
But I want to let the local application selective over-ride helper methods from AdvancedHelper in the engine (and ideally be able to call 'super'). That's a pretty reasonable thing to want to allow, right, a perfectly reasonable (and I'd think common) design?
Problem is, I can't seem to find any way to make it work. If the application defines it's own app/helpers/advanced_helper.rb (AdvancedHelper), then the one from the engine never gets loaded at all -- so that would work if you wanted to replace ALL the helper methods in there (without calling super), but not if you just want to over-ride one.
So that kind of makes sense actually, so I pick a different name. Let's call my local one ./app/helpers/local_advanced_helper.rb (LocalAdvancedHelper). This helper DOES get loaded, if I put a method in there that wasn't in the original engine's AdvancedHelper, it is available to views.
But if I put a method in there with the same name as one in the engine's AdvancedHelper... my local one NEVER gets called. It's like the AdvancedHelper (from engine) is earlier in the call chain than the LocalAdvancedHelper (from app). Indeed, if I turn on the debugger, and look at helpers.ancestors, that's exactly what's going on, they're in the reverse order I'd want in the ancestor chain. So AdvancedHelper (from engine) could theoretically call 'super' to call up to LocalAdvancedHelper (from app) -- but that of course wouldn't make a lot of sense to do, you'd never want to do that.
But what I would want to do... I can't do.
Anyone have any ideas, is there any way to provide this design, which seems perfectly reasonable to me, where an app can selectively over-ride a helper method from an Engine?
Anyone have any explanation of why it's working the way it is? I tried looking at actual Rails source code, but got lost pretty quick, the code around this stuff is awfully abstract split amongst a bunch of places.
This is pretty esoteric question, I'm pessimistic anyone will have any ideas, I hope you surprise me!
== Update
Okay, in order to understand what part of Rails code is being called where, I put a "def self.included ; debugger ; end" on each of my helpers, then in the debugger I can raise an exception to see a stack trace.
That still isnt' really helping me get to the bottom of it, the Rails code jumps all over the place and is pretty confusing.
But it's clear that a helper with the 'standard' name (ie WidgetHelper for WidgetController) is called by different rails code, to include in the 'master' view helper module for a given controller, than other helpers are. I'm wondering if I give the helper a different name, then manually include it in my controller with ("helper OtherNamedAdvancedHelper"), if that will change the load order.
We can use Module#class_eval to override.
In main app,
MountedEngineHelper.class_eval do
def advanced_helper
...
end
end
In this way other methods defined in engine helper are still available.
Thanks for your elaboration. I think this really is a problem. And it is still present in Rails 3.2.3, so I filed an issue.
The least-smelling workaround I came up with is to do a "half alias method chain":
module MountedEngineHelper
def advanced_helper
...
end
end
module MyHelper
def advanced_helper_with_extra_behavior
advanced_helper
extra_behavior
end
end
The obvious drawback is that you have to change your templates so that your helper is called. At least, you make the existence of extra behavior explicit there.
These release notes from Rails4 seem enticingly related to this problem, and potentially note it's been fixed:
http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#helpers-loading-order
Related
We are currently using Ruby 1.9.3, Rails 3.1 (i know, we're working hard to upgrade all our applications).
We're using a module (let's call it 'OurModule' to add a method (let's call it 'OurAddOnMethod' to a model defined in a gem (let'd call that 'GemModel'). We have that module file living in the 'config/initializers' directory.
That file defines the module, and then calls this to include it in the model:
# Include the extension
GemModel.send(:include, OurModule)
When developing, things work well mostly, but periodically we will get an error that basically says "Undefined method 'OurAddOnMethod' in 'GemModel'". Restarting the server resolves the issue (for a while).
I'm assuming this is happening because the models are reloaded periodically with changes made in the development environment, and it appears that the initializers do not also get reloaded at that time..? It seems like this may not be the best way to set things up; it is quite frustrating to deal with.
Can anyone enlighten me on a better way to achieve this?
I ended up using wrapping the code in the following, and keeping it in initializers:
ActionDispatch::Callbacks.to_prepare do
# configure stuff or initialize
end
I feel really bad, i completely missed this question that seems to completely cover mine (linking to the answer that i used):
https://stackoverflow.com/a/8636163/287516
I find, even when assigning the decorator #singleton(false) to the view-model, that while the view-model does then persist as a singleton across activation/deactivation, the bindings and components, etc do not.
(I assume this is because they are stored in a container that is disposed on deactivation.)
The result is that upon every deactivation/activation of a view with a singleton view-model, the view is un-bound and then re-bound.
Is it possible to cause the bindings to persist across deactivation/activation?
This one stumped me for a good while. It also confused me as to why implementing it was not a higher priority for the Aurelia Team.
This takes a fair amount of code to get working. I have put the code in a Gist here: https://gist.github.com/Vaccano/1e862b9318f4f0a9a8e1176ff4fb727e
All the files are new ones except the last, which is a modification to your main.ts file. Also, all my code is in Typescript. If you are using Javascript you will have to translate it.
The basic idea behind it is that you cache the view and the view model. And your replace the router with a caching router. So when the user navigates back to your page, it checks first to see if there is a view/view model already created and uses that instead of making a new one.
NOTE: This is not "component" level code. That means I have tested that this works for the scenario that I use it for.
I got my start for making this change here: https://github.com/aurelia/router/issues/173 There is another user (Scapal) made something that works for him and posted it there. If what I am posting does not work for you, his may help you out.
i'm also interested in an answer to this.
maybe i'm now making a complete fool out of me but why not use aurelia-history navigate(..) command?
My situation, as some background:
I'm writing a small javascript library which uses window.requestAnimationFrame to perform its animation loop. Because that function isn't standardised across the browsers yet, internally in the library it creates a polyfill-ish function in a closure.
var requestAnim = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| ...
|| function () { ... };
The issue here is that this makes it quite hard for me to test this code now. Previously, when it was using setTimeout, I would override that global function in the tests to simulate a number of frames passing synchronously.
Anyway, to the point of the question:
Right now, it seems like my options are either to leave some of my code untested, or to add extraneous features to the library with the sole purpose of making it easier to test. Neither of these options sound that great to me.
Without worrying too much about my specific case, in general, what should you do in this situation?
Yes, it is ok.
We don't write tests for the sake of testing. Testing is an acknowledgement of the fact that we aren't brillant enough to write and maintain code perfectly without safety checks. All test code serves one purpose and only one: to make a better product. This is true whether it lives in the /test folder or in the /src folder. Therefore it is a mistake to think "This is never called in production, therefore it is wrong to put it into /src!"
To be sure, there are other trade-offs to make, e.g. size (in an embedded product it makes a lot of sense to try everything you can to keep the /src folder small). But that is a completely different reason than merely "It's test-related".
I'd say it's fine to add testing code (unless some micro-optimisation is something you're testing). As Kilian was saying, nobody is perfect; this is the reason we do testing in the first place.
I +1d Kilian's answer, but I'd like to add my own ideas too:
In general, what situations would there be code that you cannot (with ease) test? This would be code that only runs under conditions, which you can't re-create on your testing machine? Perhaps it would be easier to set a variable to decide whether this code should run or not, then you can set a breakpoint and change this variable when debugging (in your JavaScript case, using Firebug or Chrome's developer tools?)
Or, like you say, add some testing code - a set of flags maybe at the top of the script, to keep it neat? Then your if statements could be something like
if(shouldRunThisCode || isTestingThisCode) {
doThisCode();
}
In short: Ofcourse it's fine to add code for the purpose of testing. I can't think of any scenarios where testing the code will require adding much code at all though. If the code is implemented and intended to run at some point under certain conditions anyway, it can never be too hard to test.
In general, code that is hard to test is badly written.1 It is superior to find the design problems your test difficulties are telling you about and fix those than to add code "just to make testing easier". Sometimes we do that anyway, because we construe the design problems as too difficult to fix -- but it should be the second choice. In your case, it sounds like the bad design you're exposing is in a library outside your control. In this case, adding code "just to make testing easier" is probably the best choice; you are unlikely to have enough control over an external library to improve its design.
In my Rails 3.1 app. Ive got a few controller's calling this block of code:
twitter_entertainment_users = Rails.cache.fetch('twitter_entertainment_users', :expires_in => 24.hours) do
begin
Timeout.timeout(10.seconds) do
Twitter.suggestions('entertainment')
puts "#{Twitter.rate_limit_status.remaining_hits.to_s} Twitter API request(s) remaining this hour"
end
rescue Twitter::NotFound
end
end
Instead of re-typing this block of code everywhere. Should I have this in a module instead? i.e. to keep things DRY?
If so, where should this go? I read somewhere about putting module code in app/concerns/foobar.rb.
Any other approach? Looking for suggestions / articles.
it's always better not to repeat your code. That way when you change something, you only have to do it in one place. (And believe me - you don't want to do it five times over and then just hope you didn't miss anything.)
Put it somewhere where all the controllers can access it. Consider making a module (or a folder) for all the helper methods you might need and keep them in one place. That way you always know where to look.
Sometimes when looking at someone else's large Objective-C program, it is hard to know where to begin.
In such situations, I think it would be helpful to log every call to every non-Apple method.
Is there a way to do that? Basically, make one change in some central place, and log every method that is called. Preferably limited to non-Apple methods.
You can set the environment variable NSObjCMessageLoggingEnabled to YES. This will write a log of all message sends in the folder /tmp/msgSends-xxx.
You could add a symbolic breakpoint to objc_msgSend(), and have it log the second parameter without stopping.
How to do it for your own methods only though is a toucher task. Maybe if you could inspect the class name being called and do some magic to have a conditional breakpoint for only calls where the class' prefix matches your own?
I don't think logging every single call is practical enough to be useful, but here's a suggestion in that direction.
On a side note, if it's a large program, it better have some kind of documentation or an intro comment for people to get started with the code.
In any case, every Cocoa application has an applicationDidFinishLaunching... method. It's a good place to start from. Some apps also have their principal (or 'main window') class defined in the Info.plist file. Both these things might give you a hint as to what classes (specifically, view controllers) are the most prominent ones and what methods are likely to have long stack-traces while the program is running. Like a game-loop in a game engine, or some other frequently called method. By placing a breakpoint inside such a method and looking at the stack-trace in the debugger, you can get a general idea of what's going on.
If it's a UI-heavy app, looking at its NIB files and classes used in them may also help identify parts of app's functionality you might be looking for.
Another option is to fire up the Time Profiler instrument and check both Hide missing symbols and Hide system libraries checkboxes. This will give you not only a bird's eye view on the methods being called inside the program, but also will pin-point the most often called ones.
By interacting with your program with the Time Profiler recording on, you could also identify different parts of the program's functionality and correlate them with your actions pretty easily.
Instruments allows you to build your own "instruments", which are really just DTrace scripts in disguise. Use the menu option Instrument >> Build New Instrument and select options like which library you'd like to trace, what you'd like to record when you hit particular functions, etc. Go wild!
That's an interesting question. The answer would be more interesting if the solution supported multiple execution threads and there were some sort of call timeline that could report the activity over time (maybe especially with user events plotted in somehow).
I usually fire up the debugger, set a breakpoint at the main entry point (e.g. - applicationDidFinishLaunching:withOptions:) and walk it in the debugger.
On OSX, there are also some command-line tools (e.g. sample and heap) that can provide some insight.
It seems like some kind of integration with instruments could be really cool, but I am not aware of something that does exactly what you're wanting (and I want it now too after thinking about it).
If one were to log a thread number, and call address, and some frame details, it seems like the pieces would be there to plot the call timeline. The logic for figuring out the appropriate library (Apple-provided or third party) should exist in Apple's symbolicatecrash script.