Free standing function in coffeescript in Rails 3.2.8 - ruby-on-rails

I've recently started using coffeescript in my rails projects pretty heavily.
I'm curious how you make a free standing function. So if I do:
foo = ->
alert("hello world")
That compiles to
(function() {
var foo;
foo = function() {
return alert("hello world");
};
}).call(this);
How do I make it compile to
var foo;
foo = function(){
return alert("hello world");
}
I want to be able to call use link_to_function "foo"

There are actually several ways you can accomplish this (one way already given in the comments).
Compile without the closure wrapper
This will expose all functions to the outer scope. This may be an option if you are using a lighterweight framework where you can control of the build process. I'm not sure you would be able to within the context of the asset pipeline but works great in the context of a small sinatra app.
coffee -b myfile.coffee
Attach to a global object
If you know you are targeting a specific runtime, like the browser you can use the global window object.
window.foo = -> alert("hello world")
This is the same effect as the solution in the comments since the target is a Rails environment. But using # which is sugar for this. will attach it to whatever the scope of this is at the moment. Assuming the function is not being defined in a callback or an internal object with a bound context, it would likely be the window object.
#foo = -> alert("hello world")
Better would be to create your own namespace and attach that way:
Mine ||= {}
Mine.foo = -> alert("hello world")
#Mine = Mine
CoffeeScript classes
Or use CoffeeScript's class syntax to do the same by attaching to the prototype itself:
class #Mine
#foo: -> alert("hello world") # called as Mine.foo() (notice the # declaration)
In our rails applications we typically have an asset that defines the namespace, aka a file at app/assets/javascripts titled mine.coffee:
window.Mine ||= {}
and then in other files we can require that namespace:
#= require mine
class Mine.MyOtherThing
#foo: -> alert("hello world")

Related

BackboneJS view keeps returning not defined

I can't seem to initialize my view. I tried looking around to see if this was asked before, but none of the solutions were working for me. My backbonejs view is below:
class FRView extends Backbone.View
el: $ 'fr_view'
initialize: ->
console.log("created")
render: ->
console.log("here")
I'm attemtpting to intialize it inside of a partial using the code below:
:javascript
var curr_view = new FRView()
but I keep getting the following error:
Uncaught ReferenceError: FRView is not defined
I've also tried
:javascript
var curr_view = new Backbone.View.FRView()
Which lead to the following error:
Uncaught TypeError: Backbone.View.FRView is not a constructor
From chrome sources browser I can see that the FRView file is loaded. I've also tried wrapping it in document onload but that didn't help. Any idea what might be causing this issue?
I see two bugs, one you know about and one that you'll find out about soon.
The first problem (the one you know about) is caused by CoffeeScript's scoping system:
Lexical Scoping and Variable Safety
[...]
Although suppressed within this documentation for clarity, all CoffeeScript output is wrapped in an anonymous function: (function(){ ... })();
So your FRView ends up looking more or less like this in JavaScript:
(function() {
var FRView = ...
})();
and that means that FRView is only visible inside your CoffeeScript file.
The easiest solution is to put the class in the global scope:
class #FRView extends Backbone.View
or equivalently:
class window.FRView extends Backbone.View
Another common solution is to define a global namespace for your app and then put your class in that namespace:
class YourNameSpace.FRView extends Backbone.View
and say new YourNameSpace.FRView when instantiating it.
The other problem is that your el looks a bit confused:
el: $ 'fr_view'
There are two problems here:
That will be looking for an <fr_view> element in your HTML and you probably don't have such a thing. I'd guess that you really have something like <div id="fr_view"> or maybe <div class="fr_view">, in that case you'd want to say:
el: '#fr_view' # If you're using an id attribute.
el: '.fr_view' # If you're using a CSS class.
$ 'fr_view' will be executed when the JavaScript is loaded and the element might not exist at that time. The solution to this problem is to use just the select for el as above. There's no need to use a jQuery object for el, Backbone will do that for you when the view is instantiated.
As 'mu is too short' pointed out, the issue rooted from namespace/declaration issues. After googling around about namespace I skimmed through this and fixed the issue by changing my backbonejs view to:
class Portal.Views.FRView extends Backbone.View
el: $ '#FRView'
initialize: ->
console.log("created")
render: ->
console.log("here")
and instantiated it using:
:javascript
var frview = new Portal.Views.FRView();

How do you include a raw, uncompiled partial in dust.js?

I have dust working reasonably well, but I'd like to be able to include a file, such as a css file, without compiling and rendering it.
It seems like maybe I need to create an onLoad handler that loads the file and registers the content directly.
Is there a way to do this within dust already?
You can take advantage of Dust's native support for streams and promises to make file inclusion really nice. The exact implementation depends on whether you're running Dust on the server or the client, but the idea is the same.
Write a helper that loads the file and returns a Stream or Promise for the result. Dust will render it into the template asynchronously, so doing file I/O won't block the rest of the template from processing.
For simplicity, I'll write a context helper, but you could also make this a Dust global helper.
{
"css": function(chunk, context, bodies, params) {
// Do some due diligence to sanitize paths in a real app
var cssPrefix = '/css/';
var path = cssPrefix + context.resolve(params.path);
return $.get(path);
}
}
Then use it like this:
{#css path="foo/bar.css"}{.}{/css}
Or a streamy version for the server:
{
"css": function(chunk, context, bodies, params) {
// Do some due diligence to sanitize paths in a real app
var cssPrefix = '/css/';
var path = cssPrefix + context.resolve(params.path);
return fs.createReadStream(path, "utf8");
}
}

Requiring a LuaJIT module in a subdir is overwriting a module of the same name in the parent dir

I have a file setup like this:
main.lua (requires 'mydir.b' and then 'b')
b.lua
mydir/
b.so (LuaJIT C module)
From main, I do this:
function print_loaded()
for k, v in pairs(package.loaded) do print(k, v) end
end
print_loaded()
require 'mydir.b'
print_loaded()
-- This would now include 'mydir.b' instead of 'b':
local b = require 'b'
The outputs of the prints show that my call to require 'mydir.b' is setting the return value as the value of package.loaded['b'] as well as the expected package.loaded['mydir.b']. I wanted to have package.loaded['b'] left unset so that I can later require 'b' and not end up with the (in my opinion incorrectly) cached value from mydir.b.
My question is: What's a good way to deal with this?
In my case, I want to be able to copy around mydir as a subdir of any of my LuaJIT projects, and not have to worry about mydir.whatever polluting the module namespace by destroying any later requires of whatever at the parent directory level.
In anticipation of people saying, "just rename your modules!" Yes. I can do that. But I'd love to know if there's a better solution that allows me to simply not have to worry about the name collisions at all.
The problem was that I was calling luaL_register incorrectly from within my b.so's source file (b.c).
Here is the bad code that caused the problem:
static const struct luaL_reg b[] = {
/* set up a list of function pointers here */
};
int luaopen_mydir_b(lua_State *L) {
luaL_register(L, "b", b); // <-- PROBLEM HERE (see below)
return 1; // 1 = # Lua-visible return values on the stack.
}
The problem with the highlighted line is that it will specifically set package.loaded['b'] to have the return value of this module when it's loaded. This can be fixed by replacing the line with this:
luaL_register(L, "mydir.b", b);
which will set package.loaded['mydir.b'] instead, and thus leave room for later use of a module with the same name (without the mydir prefix).
I didn't realize this until long after I asked this question, when I finally got around to reading the official docs for luaL_register for Lua 5.1, which is the version LuaJIT complies with.

LuaJ How to avoid overriding existing entries in Globals table

I am loading different Lua scripts using LuaJ into the globals environnment as follows in Java:
globals = JmePlatform.standardGlobals();
LuaValue chunk = globals.load(new FileInputStream(luaScriptA), scriptName, "t", globals);
chunk.call();
My problem is that if for example the scriptName happens to be require, print, error, math or any other name that already exists in globals after calling
globals = JmePlatform.standardGlobals();
, the script will in fact replace/override the actual functionality such as print.
Is there any simple way to prevent this from happening?
Unfortunately a test such as:
if (globals.get(scriptName) != Globals.NIL) {
//then dont allow script load
}
will not work for me as there are cases that it should actually override an existing script, when the script is updated.
I recommend never storing libraries in the global scope, for exactly this reason. See http://www.luafaq.org/#T1.37.2 for a way of loading modules and libraries using required. I'm not sure if this works on LuaJ, but if it implements require correctly, you can make a loader function and put it in package.loaders.
Basically, you define your libraries like this:
-- foo.lua
local M = {}
function M.bar()
print("bar!")
end
return M
And import them like this:
-- main.lua
local Foo = require "foo"
Foo.bar() -- prints "bar!"
See the documentation of require for implementing the loading function.

Under Rails3.1.1/Coffeescript - not always getting the function safety wrapper

I have recently started using coffeescript with Rails and I am finding that sometimes the generated javascript does not get the function safety wrapper.
Here is a sample project demonstrating it.
For example, this CS code, in index.js.coffee:
class Foo
afunc: ->
alert("afunc")
Correctly becomes:
(function() {
var Foo;
Foo = (function() {
function Foo() {}
Foo.prototype.afunc = function() {
return alert("afunc");
};
return Foo;
})();
}).call(this);
But this code, from other.js.coffee:
class App.Func
ouch: ->
alert("ouch")
becomes this un-wrapped version
App.Func = (function() {
function Func() {}
Func.prototype.ouch = function() {
return alert("ouch");
};
return Func;
})();
It seems to be due to the "App." prefix - which I can see affects naming/scope - but why is coffeescript compiling it differently...
App is defined in setup.js.coffee, like this:
window.App =
Models: {}
Which also does not get wrapped, unless I add a class into that file too.
I am sure it must be my misunderstanding - so thanks in advance for the pointers to the manual :).
EDIT:
I created this question as I thought it might be behind some issues I was having with my backbone/coffeescript app, but it seems that it was not. As the class is linked to a public/global thing "App", it seems to work wrapped or not. Still would be useful to know why its happening - is it by design?
The "function safety wrapper" feature you are using works to prevent local variables from being set on the global namespace. Since setting an object property (App.Func) doesn't affect the global namespace, the declaration is not wrapped in a function.

Resources