Ember Leaflet is an incredibly powerful and well-designed addon for Ember 1 and 2. Miguel Andrade did a fantastic job of updating the original project for Ember 2.0 and writing some great documentation. The documentation does not, however, cover extending components and modifying their event listeners. Here are some tips for dealing with those issues.
New Locations for Addon Components
All of the layer components that were in the ‘layers’ directory of the addon in the first version are now in the ‘components’ directory. Your import statement goes from:
There’s no officially supported way to override event listeners in this new version of Ember Leaflet, but, as Alex Grant pointed out in a GitHub issue, there is an undocumented way to do this - write a function whose name corresponds to a Leaflet event prefixed with an underscore. So:
123
_click(e){alert('You just clicked a marker!');}
This works because of the way that Ember Leaflet assigns event listeners to each component’s underlying Leaflet object when the component is initialized. There are more details about this in the aforementioned issue.
Accessing a Component’s Leaflet Object
While you can add another event listener using the underscore method described above, removing the default behavior requires accessing the component’s underlying Leaflet object. This object is the component’s _layer property, and it’s created when Ember Leaflet calls the component’s layerSetup() function.
I was able to remove a default event listener of the Leaflet object by defining a layerSetup() function for my custom component and then using Ember’s _super() function to call the parent component’s function.
My goal in digging into this was to override the default marker click event only in a certain state. I haven’t yet worked out the details here, but I have at least sorted out extending the component, removing the default click event, and defining a new click event.
This is the basic jist of my custom component right now.
1234567891011
importMarkerLayerfrom'ember-leaflet/components/marker-layer';exportdefaultMarkerLayer.extend({layerSetup(){this._super();this._layer.off('click');},_click(e){alert('You just clicked a marker!');}});
Let me know if you have any ideas! I’ll update this post when I’ve finished that last step.
Though they’re rarely used, Ruby supports sets - unordered collections of unique objects. The Set class isn’t required by default, so you’ll have to require 'set', and the constructor is a little verbose compared to that of an array or a hash1, but sometimes they’re just what you need.
They have a couple of big advantages over Ruby’s arrays and hashes:
A set only contains unique elements, which makes uniqueness checks unnecessary. Adding an element to a set that is already a member of that set will fail silently.
While looking up an element by index is not possible (as it is with Array), looking up an element is faster than in an array2. This is, as the Ruby documentation says, because “Set uses Hash as storage.”
In addition, the Set class introduces some interesting methods (including #disjoint?, #intersect?, #classify, and #divide) and operators. Perhaps the most useful of these are & (the intersection operator), | (the union operator), - (the difference operator), and ^ (the exclusion operator). All but the last of these can also be used with arrays in Ruby.
You have to use the explicit constructor (Set.new [1, 2, 3, 4] or Set[1, 2, 3, 4]). You can also turn an array into a set with the #to_set method. ↩
This is because arrays are really best at index lookups. ArrayFields is an interesting Ruby library that appears to combine the best of hashes and arrays, adding fast keyword lookup using the same syntax as hashes. ↩
As a musician, engineer, and web developer, it has been very exciting to watch the Web Audio and WebRTC APIs mature. A robust platform for audio on the web has the potential to usher in a new era of collaborative music creation and social audio sharing. While native desktop DAW applications such as Pro Tools, Logic, Ableton Live, FL Studio, GarageBand, Digital Performer, and Cubase have grown more powerful and flexible over the last several years, facilities for collaboration and social sharing haven’t really kept pace.1 Perhaps the DAW of the future will be a web application, something like the audio equivalent of Google Docs.
I can dream. Or I can take things apart, see how they work, and then build new things.
recorder.js
In this post, I’ll walk through a popular demo of recording with the Web Audio API. In the process, I’ll touch on the basics of the Web Audio API, Web Workers, and WebRTC, a trio of fledgling web technologies that combine to allow us to record and process audio in the brower.
The AudioRecorder demo is simple recording interface comprising three parts: an animated spectrograph of the client’s current audio input, a record button that starts and stops recording audio (and displaying the recorded audio’s waveform) from that input, and a save button that allows the user to download the recorded audio as a WAV file. I’m just going to focus on the latter two here, those responsible for recording audio, displaying the audio’s waveform while recording, and finally saving the recording. Most of this functionality comes from Matt Diamond’s fantastic recorder.js plugin.
Like most JavaScript that takes advantage of bleeding-edge browser features, this application’s Javascript begins with a whole bunch of feature detection to make sure that the browser is capable of animating the audio display and obtaining an audio stream using WebRTC. At this time, the WebRTC is partially implemented in some browsers and not supported at all in several browsers. It provides access to a video and/or audio stream from the user using navigator.getUserMedia(), which takes a parameter of constraints. The constraints are either optional or mandatory. In this case, the recorder is using the mandatory constraints to disable a handful of default audio behaviors in Chrome.
Now we get into the Web Audio API, which allows us to work with audio in the browser. It is quite well-supported in modern browsers. Much as the HTML <canvas> element allows us to get a 2D or 3D drawing context in JavaScript, the AudioContext() constructor gives us a context in which we can connect sound sources and destinations (which the Web Audio API collectively calls AudioNodes). Everything that the Web Audio API does happens within AudioContext objects, which are directed graphs of AudioNodes that are responsible for receiving, producing, transforming, and emitting audio signals.2 In this way, it works similarly to my beloved Minimoog compact modular synthesizer from the 1970s, with its oscillators, mixer, and filters, or to a recording studio with its many microphones, processors (EQ, compression, effects, and so on), mixing console, and recording devices (tape machines and computers).
In this case, the callback passed to getUserMedia(), gotStream(), is called when the stream is successfully obtained and goes about creating a bunch of AudioNodes on the context and connecting them. There’s an inputPoint node for controlling gain, a realAudioInput for actually getting the audio, an analyserNode for performing a Fourier transform on the audio (this is for displaying the spectrograph or “analyser”), and finally a zeroGain node that is the endpoint of the audio in the context. The recorder just records audio and doesn’t actually output any audio directly, so the zeroGain just receives the audio at the end of the chain and silences it. Right before that connection is made, a new Recorder object is created with the stream from getUserMedia() as its source.
Okay, so that covers the initialization of the application. The rest of the application, save the analyzer that I won’t cover in detail here, is event driven. The toggleRecord() function is triggered by the click event on the record button, which in turn either stops or starts the recording.
We’ll start with the recorder activation. clear() is called on the instance of Recorder created in gotStream(), followed by record(). The methods are implemented in Matt Diamond’s recorder.js.
Part 2: recorder.js
The Web Audio API provides many pre-built AudioNode objects that cover most use cases that are generally written in a lower-level language than JavaScript (usually C or C++). However, it’s also possible to create your own processing object directly in JavaScript using the createScriptProcessor() method of AudioContext, which is how Mr. Diamond deals with recording audio in recorder.js.
In addition, Mr. Diamond’s recorder.js makes use of the Web Worker API, another relatively new browser API that gives developers the ability to run background processes. The API, which is quite well-supported in modern browsers, exposes a constructor function, Worker(), that takes an argument of the JavaScript file that will run on its own thread in the background. The worker in recorder.js is assigned to the recorderWorker.js file, which we’ll get to in a moment.
The Recorder() constructor begins by creating a script processor and setting a buffer length for recording audio. Communication between a worker and the script that spawned it is achieved through message passing, so this function then passes the ‘init’ message to the worker along with a config object that specifies the sample rate.
The worker script contains all of the guts of the recorder. The entire process of passing audio from the left and right channel input buffers to the recording buffers and creating a WAV file from those buffers is encapsulated in this worker. The switch statement on the ‘onmessage’ event at the top of the function, which receives the ‘command’ and ‘buffer’ parameters sent from recorder.js, controls the workers behavior - the ‘record’, ‘exportWAV’, ‘getBuffers’, and ‘clear’ messages kick off those actions in the worker.
Intermission
I’ll be updating this post with more details on this worker and the recorder.js flow at a later date. In the meantime, make some noise at your laptop.
Soundcloud and Bandcamp are fantastic platforms, but because neither of them provide any creation tools (unlike platforms like Instagram and Vine), they’re largely out of reach for non-professional users. ↩
I was perusing the paperclip gem’s source code when I came upon the following line (lib/paperclip/interpolations.rb, line 178):
1
("%09d".freeze%id).scan(/\d{3}/).join("/".freeze)
It’s a useful bit of code for saving attachments to a filesystem, but what struck me immediately was the preponderance of #freeze calls. What the hell is #freeze anyway?
There are a couple of reasons you might want to use it.
1. Making an Object Immutable
Ruby constants are really just variables that you shouldn’t change. Ruby will warn you if you change a constant, but it won’t raise an exception. So, if you really want to have Ruby enforce the constancy of a constant, you can freeze that object.
Remember that when you assign a frozen object to a variable, this does not prevent the variable from being reassigned to another object. The following code, for example, works just fine:
You can extend this to create a whole class of objects that are constant from birth - just call #freeze at the end of a class’s initialize function definition. This might come in handy if you’re trying to write Ruby in a functional style, or if you need to prevent a programmatically important string (such as a hash key) from being modified by some other code.
2. Performance
As great as this is, this is not why the paperclip developers used #freeze three times in that line at the beginning of this post.
They used it to optimize for performance. Because a frozen object can’t be modified, frozen objects in Ruby are only instantiated a single time for each unique object1 and then retained to be reused in the future. Symbols, fixnums, bignums, and floats are all frozen by default. Strings, however, aren’t, and it’s pretty common for the same string literal - such as the format string in the above example - to be called many, many times in an application.
Therefore, freezing a string literal that you don’t ever intend to modify (such as "/" and the format string "%09d" in the example above) in a method that gets called multiple times can result in substantial memory savings and faster performance. Ruby will allocate those string objects the first time the method is called and then just reference those existing string objects on every subsequent call.
An Immutable Future
For these and other reasons, strings are immutable in several other modern languages, such as Python, Java, C#, and Go, and Ruby is moving in the direction of freezing strings by default, too. Starting with Ruby 2.2, strings used as hash keys are frozen by default, and Ruby 3.0 will freeze all string literals by default. You can see what life is like with frozen string literals right now with the frozen_string_literal pragma, which is available in Ruby 2.3 or later.
With frozen strings, one can take advantage of the wide array of methods available to String objects without incurring the performance penalty of instantiating loads of identical objects all the time. You can also make use of external libraries, in the form of gems, middleware, or whatever, that might force you to use strings in certain places where you might normally prefer symbols. Symbols, for example, are usually used for hash keys, but some software might expect strings are hash keys. Frozen strings bring many of the benefits of using symbols while maintaining compatibility.
Frozen strings are also a good choice for creating objects based on user input. As Richard Schneeman points out in his excellent post about string keys in Ruby 2.0, creating symbols based on user input can lead to a particular sort of denial of service attack and other potential security problems. The JSON gem suffered from this vulnerability before Ruby 2.0.0, and Mr. Schneeman has some other examples of this vulnerability in his post about symbol garbage collection in Ruby 2.2. Ruby now garbage collects dynamically generated symbols, so this vulnerability isn’t an issue in the latest versions of Ruby, but older versions are common enough that this is still a real concern.
Even though Ruby will soon be freezing strings by default, the absolute fastest way to freeze a string is to do it manually. Embrace it. It’s the low-hanging fruit of Ruby optimization. So, when you’ve written an application or a gem or anything in Ruby and you’re looking to speed it up or reduce its memory footprint, look to #freeze.2
This is not strictly true in newer versions of Ruby - dynamically generated symbols (created using #to_sym) are garbage collected. ↩
Mr. Schneeman has written another pretty comprehensive post about #freeze and memory usage that focuses specifically on memory optimization and suggests several tools for profiling your Ruby code for memory usage. ↩
I tried to make a class Enumerable by dynamically mixing in the Enumerable module and defining #each after declaring the class. I failed. This is my story.
I was messing around with dynamically mixing in Ruby modules. One of the most useful modules in Ruby is the Enumerable module. It’s a total badass. So I thought I’d try mixing it into a class that I had already defined and see if that worked out.
The first step is including it dynamically. Maybe I can just call the include method on my class!
1
MyClass.include(Enumerable)
Okay! That appears to work. No exceptions. Now let’s use it. I’ll try out using #reduce, one of my favorite higher-order functions in Ruby.
12
my_thing=MyClass.newmy_thing.reduce{|thing|putsthing}# => NoMethodError: undefined method `each' for #<MyClass:0x007fe59c0e3588>
Oops. In order to take advantage of the Enumerable module, you need both to include the module and define your own #each method.1 This makes a lot of sense - how can your class be enumerable in there’s nothing to enumerate?
I could just define #each in my class definition and be done with it, but this is all about exploring the process of dynamically modifying classes. Let’s just just pretend that doing that is not an option here and we want to add this instance method to the class after it’s been defined.
Defining an instance method for a class after the class definition, however, is pretty awkward. We can’t just use the dot syntax on our class, becuase that would definite our #each for just that one instance of MyClass. The best way to do this is to use #define_method. We can also use Class#class_eval, and it may be preferable from a performance perspective, but it’s not very readable and unless we absolutely need to squeeze every ounce of performance out of this code, we should probably avoid it. Also, that’s too easy. Let’s make this harder. Let’s use #define_method.
The problem here is that #define_method is a private method that every class inherits from Module. So we can’t just call MyClass.define_method. We have to either create a method in the class definition that in turns calls #define_method for us,
All instances of MyClass will now have our #each. Great. Let’s try using it now!
12
my_thing=MyClass.newmy_thing.map{|thing|putsthing}# => no block given (yield) (LocalJumpError)
What? LocalJumpError? No block given? I definitely just passed in a block. What went wrong?
Block as Closures and the Behavior of yield
This is where we get into the hairy business of Ruby’s closures. Closures are a bit of a strange concept, especially in the context of object-oriented programming, in which we rely on objects for pretty much everything. Still, it’s worth knowing about closures, Ruby has them, and understanding them will help you in certain other functional or functional hybrid languages, such as JavaScript. Alan Skorkin has a nice, succinct definition of closures on his blog:
A closure is basically a function/method that has the following two properties:
• You can pass it around like an object (to be called later)
• It remembers the values of all the variables that were in scope when the function was created. It is then able to access those variables when it is called even though they may no longer be in scope.
I recommend Mr. Skorkin’s post about closures. It’s clear and precise and covers both Ruby’s implementation of closures and some common uses of closures. If closures are confusing to you, as they were to me, go ahead and read this post and come back when you’re finished.
Ruby blocks are closures (or at least almost closures - see the second footnote). When you create a block and pass it to a method, it closes over all of the variables and constants in its lexical scope. Here’s the crazy thing: Ruby blocks also close over blocks. They are insane cannibal constructs. So, the problem here is that the yield in the body of my #each is actually yielding to the implicit block (whether it’s passed or not) passed to #create_method. Crazy pants.
As Paul Inning says in his encyclopedic discussion of Ruby closures, “yield can only refer to the block passed to the method it’s in.”2 John Mair, creator of our beloved Pry REPL, believes that this is actually pretty consistent behavior, and that makes sense to me - because blocks close over blocks, any method can receive a block, and a method can handle only one block at a time, yield has to just refer to the block passed to the method in which it finds itself.
Phew. Okay, fine, I’ll just use Class#class_eval. Or maybe I’ll just actually include Enumerable and define #each like a normal human being.
Also note that (from the Ruby documentation) “If Enumerable#max, #min, or #sort is used, the objects in the collection must also implement a meaningful <=> operator, as these methods rely on an ordering between members of the collection.” ↩
He also says that this means that blocks aren’t true closures - we can’t pass them around. We can only send them to a method and use yield to invoke them. In other words, they’re not first-class functions. This is true. ↩
The #map and #reduce functions are most closely associated with functional programming.1 Even so, Ruby, the object-oriented-est of all object-oriented programming languages, has robust implementations of both of these extremely expressive higher-order functions. I’m going to explore how to use these methods and what you can do with them, especially when you use them together. This will be pretty exhaustive, so be prepared for a very long blog post.
First, the Basics
As higher-order functions, each of these methods accepts a function in the form of a block. They then iterate over an enumerable object and call this block on each iteration. Where they differ is in what they do with the result of this block.
#map (or #collect) returns an array containing the results of calling the supplied block on each element of the enumerable. In other words, map allows you to apply a function to every element of a data structure and receive the result.
#map is usually called with a block, as in collection.map { |element| element + 1 }. If collection = [1, 2, 3, 4], this will return [2, 3, 4, 5]. As with many other methods from the Enumerator module, if #map is called without a block, it will return an Enumerator.2
#reduce (or #inject) returns a value that is the result of applying a binary operation to the return value of applying the supplied block to each element of the enumerable. Whoa. What a mouthful. In other words, #reduce “reduces” each element of an enumerable to a single value, accumulates that value in a single variable, and then returns the value of the accumulator. Some functional languages, such Scheme and OCaml, refer to this function as fold.
The simplest use of #reduce is just collection.reduce(initial_value, :name_of_method). For example,
calls the #+ for each element in the array. The method that we specify (in this case, #+) has to be a binary method (a method called on one object with a single argument of another object), so we need a starting value, which we have in this case specified as 0. As we iterate through the array using reduce, this is what happens at each stage of the iteration:
1234567891011
# reduce sets up an accumulator variable, memo, and sets it to the initial# value, which is 0.memo=0# Now we hit the first element of the array.memo.send(:+,1)# => 1# The line above is the same as memo += 1 or memo.+(1).memo.send(:+,2)# => 3memo.send(:+,3)# => 6# This is the last time through the array, so the value of memo at the end# of this is the return value for reduce.memo.send(:+,4)# => 10
There’s also the option of passing a block instead of the name of a function, which would look like
1
array.reduce(0){|sum,element|sum+element}# => 10
for the example above.
If you don’t declare an initial value, the initial value will be the first element of the collection. This is very important! If, for example, you have an array of objects and you’re using #reduce to get the sum of an attribute, leaving out an initial value will lead to strange and undesirable results.
Some Interesting Map and Reduce Examples
These functions are very powerful when used together. First, I’ll look at a couple of examples of using #map and #reduce on their own, and then I’ll get into an example of using reduce chained on to the end of map.
Let’s break this not-quite-recursive code down into separate steps.
Mr. Grzesiak splits module_name, which is our starting string, on the scope resolution operator into the array [“X”, “Y”, “Z”].
He then uses #inject with the inject(initial) syntax, which will initialize the accumulator, called memo, to an empty array.
Now the iteration begins. If this new ‘memo’ array is empty, which will only happen on the first iteration of #inject, #inject adds that element (“X”) to the beginning of memo (using Array#unshift). Otherwise, #inject adds a string to memo containing the result of the previous iteration (“X”), the separator (“::”), and the current element (“Y”).
So, the final array is built backwards: [“X”], then [“X::Y”, “X”], and then finally [“X::Y::Z”, “X::Y”, “X”]. Nifty. There’s a recursive solution to this problem, but it’s not nearly as clear and concise. This is a great example of how higher-order functions can be used as an alternative to recursion.
# Returns +text+ wrapped at +len+ columns and indented +indent+ spaces.# By default column length +len+ equals 72 characters and indent# +indent+ equal two spaces.## my_text = 'Here is a sample text with more than 40 characters'## format_paragraph(my_text, 25, 4)# # => " Here is a sample text with\n more than 40 characters"defformat_paragraph(text,len=72,indent=2)sentences=[[]]text.split.eachdo|word|ifsentences.first.present?&&(sentences.last+[word]).join(' ').length>lensentences<<[word]elsesentences.last<<wordendendindentation=" "*indentsentences.map!{|sentence|"#{indentation}#{sentence.join(' ')}"}.join"\n"end
There’s nothing too remarkable about this method and its use of map, but I’m going to break it down because it’s a good example of #map in some very widely used code. This code is proobably executing somewhere at this very moment.
As the comment says, this method format_paragraph takes a chunk of text that needs formatting, a line length that defaults to 72, and an indent length (in spaces) that defatuls to 2. There are two steps to this process: first break the text into lines, and then indent each line by the specified indent size.
In the first step, our function creates an array of arrays sentences, each array of which comprises the strings that make up each line. The combined character count of the words in each of these nested arrays is not greater than the specified line length (len).
The second step is where we use map to add the proper indentation to each line. After building up the indentation as a string of whitespace using String#*, our function mutates the array of line arrays by using #map! to join the words with a space (rebuild then sentence) and prepend the indentation spaces. Then the lines are all joined with line breaks. Now we have a formatted paragraph.
Map and Reduce in Tandem
Haitham Mohammad put #transposethrough its paces on Ruby Quicktips, the same site that gave us the above solution. #transpose, according to the Ruby documentation, “assumes that self is an array of arrays and transposes the rows and columns.” In other words, if you imagine an array of arrays as rows in a table, #transpose will return the columns from that table.
Mr. Mohammad then shows us how to get the sum of each column of table represented by an array of row arrays.
So there’s a bit about #map and #reduce. There’s a lot more to discuss - for example, these methods can take lambdas, too! - but this is already a very long post.
I love these guys.
Lisp, one of the oldest high-level programming languages, pioneered the use of higher-order functions. While it supports several different programming paradigms, Lisp and its most popular dialects, Common Lisp and Scheme, are most commonly used to program in the functional programming paradigm. ↩
Enumerators are a large topic in and of themselves - for more information, see the Ruby documentation. ↩
I’m curious as to the exact context for this problem. Obviously this has something to do with parsing a call to a class or module that uses the scope resolution operator, but if anyone has any more detils, let me know. ↩