Global meteor collection in closure for Coffeescript - coffeescript

If I declare a global collection as below:
#Matches = new Meteor.Collection "Matches"
How can I find a consistent way to access it in a closure on both the server- and client-sides of Meteor?
For example, the below doesn't work, since # refers to this (which is not the top-level namespace in the closure)
Meteor.publish("current-matches", ->
return #Matches.find(round: 0) # #Matches doesn't work since `this` is something else
)

Put your collection definitions in a shared directory so they will be seen by both the client and the server. You can then use them without the #. For example:
collections/matches.coffee
#Matches = new Meteor.Collection 'matches'
server/server.coffee
Meteor.publish 'current-matches', ->
Matches.find round: 0

Related

How to do computed values in Coffeescript with MobX 4?

Using MobX 3 in Coffeescript, I could do this:
mobx = require 'mobx'
state = mobx.observable
items:['a','b']
compute = (key,fn)->
obj = {}
obj[key] = mobx.computed fn.bind state
mobx.extendObservable state, obj
compute 'num', ->
#items.length
mobx.autorun ->
console.log "items = #{state.items}"
mobx.autorun ->
console.log "num = #{state.num}"
state.items.push 'c'
...which works as expected,
but with MobX 4 that same codes gives the error:
Error: [mobx] Passing a 'computed' as initial property value is no
longer supported by extendObservable. Use a getter or decorator
instead
All of the examples that I can find use Javascript with Classes and Decorators and Getters.
But Coffeescript does not really do "decorators" or "getters", and I would prefer not to use Classes ( I am old-school )
So...how can I create a computed "num" on my "state"?
Can my "compute()" function be altered to make it all work again?
Ok, I figured-out how to do it, and since there have been no answers....here it is:
compute = (key,fn)->
Object.defineProperty observable_state, key,
get: fn
configurable: true
obj = {}
obj[key] = mobx.computed
mobx.decorate observable_state,obj
First, you create a configurable "getter" (it must be configurable because MobX is going to re-configure it), then you call the "decorate" function ( instead of using ES6 decorators ).

Matching optional query parameters using the variable name

I want to create a hash of optional query parameters that are sometimes passed to my subroutine. Sometimes a query parameter called welcome is passed in, and the value is either 1 or 0.
If that variable exists, I want to add it to a hash.
I've created a configuration value called OPTIONAL_URL_PARAMS which is a list of expected parameter names that can be passed in:
use constant OPTIONAL_URL_PARAMS => ("welcome")
So far I have:
my $tempParams = {};
if ( $optionalParam ) {
foreach my $param (#{&OPTIONAL_URL_PARAMS}) {
if ($optionalParam eq $self->{$param}) {
$tempParams->{$param} = $optionalParam;
$tempParams->{$param} =~ s/\s+//g; # strip whitespace
}
}
}
But this tries to use the value of $self->{$param} instead of its name. i.e. I want welcome to match welcome, but it's trying to match 1 instead.
I know when it comes to keys in a hash you can use keys %hash, but is there a way you can do this with regular variables?
Edit
My subroutine is being called indirectly:
my $url_handler = URL::Handler->new($param, $optionalParam);
sub new {
my $class = shift;
my $args = #_;
my $self = {
param => $args{param},
optionalParams => $args{optionalParam}
};
}
If $optionalParam's variable name is 'welcome', then I want to try and map it to the constant welcome.
This is not an answer any more, but I cannot remove it yet as there is still a discussion going on to clarify the question.
foreach my $param (#{&OPTIONAL_URL_PARAMS}) {
# ...
}
The return value of OPTIONAL_URL_PARAMS (you already got an error here and that's why you have the &, that should have told you something...) is simply a list, not an array ref. Actually at this point it should throw an error because you cannot use 1 as an array reference.
Edit
In Perl, when you pass arguments to a subroutine, all the values are flattened into a single list (reference). Specifically, if you are passing parameters to a sub, the sub doesn't know the names of the variables you originally used. It only knows their values. Therefore, if you want names as well as values, you have to pass them separately. An easy way is using a hash. E.g., in new():
my $class = shift;
my $param = shift; # The first, required parameter
my %therest = (#_); # Optional parameters, if any
Then you can say URL::Handler->new($param, 'welcome' => 1), and $therest{welcome} will have the value 1. You can also say
URL::Handler->new($param, 'welcome'=>1, 'another'=>42);
and %therest will have the two keys welcome and another.
See also some further discussion of passing whole hashes as parameters
Original
This also probably doesn't answer the question!
Some thoughts on the code from your comment.
my $url_handler = URL::Handler->new($param, $optionalParam);
sub new {
my $class = shift; # OK; refers to URL::Handler
my $args = #_; # Problematic: now $args is the _number_ of args passed (list #_ evaluated in scalar context).
my $self = {
# There is no %args hash, so the next two lines are not doing what you expect.
# I actually don't know enough perl to know what they do! :)
param => $args{param},
optionalParams => $args{optionalParam}
};
}
Some thoughts:
use strict; and use warnings; at the top of your source file, if you haven't yet.
I can think of no languages other than Algol 60 that support this idea. It goes against the idea of encapsulation, and prevents you from using an array or hash element, a function call, a constant, or an expression as the actual parameter to a call
Variable names are purely for the convenience of the programmer and have no part in the functionality of any running program. If you wished so, you could write your code using a single array #memory and have "variables" $memory[0], $memory[1] etc. But you would be bypassing the most useful part of compiler technology that allows us to relate readable text to memory locations. It is best to consider those names to be lost once the program is running
The called code should be interested only in the values passed, and it would be a nightmare if the name of a variable passed as an actual parameter were significant within the subroutine
If you were able to access the name of a variable passed as a parameter, what do you suppose would be provided to subroutine stats if the call looked like this
stats( ( $base[$i] + 0.6 + sum(#offset{qw/ x y /}) + sum(#aa) ) / #aa )
In summary, it cannot be done in general. If you need to associate a value with a name then you should probably be looking at hashes
Your code
my $url_handler = URL::Handler->new($param, $optionalParam);
sub new {
my $class = shift;
my $args = #_;
my $self = {
param => $args{param},
optionalParams => $args{optionalParam}
};
}
has a number of problems
You correctly shift the name of the class from parameter array #_, but then set my $args = #_, which sets $args to the number of elements remaining in #_. But the value of $args is irrelevant because you never use it again
You then set $self to a new anonymous hash, which is created with two elements, using the values from hash %args. But %args doesn't exist, so the value of both elements will be undef. Had you put use strict and use warnings 'all' in place you would have been alerted to this
The keys that you're using to access this non-existent hash are param and optionalParam, and I think it's more than a coincidence that they match the names of the actual parameters of the call to new
While Perl is unusual in that it allows programmatic access to its symbol tables, it is an arcane and unrecommended method. Those names are essentially hidden from the program and the programmer and while modules like Exporter must manipulate symbol tables to do their job, any such behaviour inside base-level software is very much to be avoided
Finally, you never use $self again after defining it. You should be blessing it into a class according to the $class variable (which contains the string URL::Handler) and returning it from the constructor
I hope this helps

Applying Roles at Runtime from Method Modifier

I have a role that provides a method modifier like so:
package MyApp::Role::MenuExtensionRed;
use Moose::Role;
requires 'BuildMenu';
after 'BuildMenu' => sub {...};
Due to requirements elsewhere, I need to apply a number of roles at runtime, like so:
package MyApp::MainMenu
before 'BuildMenu' => sub {
my ( $self, $args ) = #_;
my $roles = $args->{menu_extensions};
apply_all_roles($self,#$roles);
};
sub BuildMenu {...}
However, the 'after' method modifier is never called. Clearly I'm breaking some rule, but I'd really like to understand why this doesn't work!
It works if instead of applying the roles before 'BuildMenu', I apply them in the BUILD method. But unfortunately, my list of menu_extension roles isn't available at that point, so I have to wait.
Any alternate solutions would be appreciated!
EDIT Interestingly, after 'BuildMenu' IS called, but only on subsequent calls to BuildMenu. So a method's modifiers cannot be altered from within another of it's own modifiers. Is this expected behavior? Is there a way to add to the "list" of modifiers at runtime?
Thats a side effect of how its implemented.
When you use a method modifier, they basically replace the existing method with a new one, and the new one contains a reference to the old.
So when you see
before foo => sub {
}
What happens at role composition time is:
my $orig = *package::foo;
*package::foo = sub {
$beforetrigger->( #args );
return $orig->( #args );
}
More or less.
So imagine, you have 2 subs, "A", the version of BuildMenu that gets invoked before applying the role, and "B", the version of BuildMenu that gets invoked after applying the role.
So what happens, is your calling order pans out like this:
First Call ->
A ->
before ->
apply roles ->
replace A with B
<-- return from before
A body ->
<-- return from A Body
Subsequent Call
B -> something
Etc, so, what I think you need to do, is have your wrapping code acknowledge this, and pass control over after application.
around foo => sub {
my ( $orig, $self , #args ) = #_;
# apply role to $self here
# this gets the sub that will be resolved *after* the role is applied
my $wrapped_sub = $self->can('foo');
my $rval = $wrapped_sub->( $self, #args );
return $wrapped_sub->( $self, #args );
}
Note there's the potential for that code to have a fun thing where $wrapped_sub is the sub I just wrote to apply the roles, ... I haven't worked out exactly what will happen there yet, but you may need to put in some conditions to prevent a self-calling-sub death loop from occurring.
But the gist of the problem essentially boils down to the fact you can't replace a sub that is executing, with a new sub, from the sub itself, and expect it to daisy chain automatically, Because the sub being replaced is not inherently aware of it being replaced, and because "method modifiers" amount to replacing subs with new ones that chain to old ones =)

Return value in perl XML::DOM

I am working on a Perl code using XML::DOM.
I found in Perl help(XML::DOM::Node) stating as below.
#list = $node->getChildNodes; # returns a perl list
$nodelist = $node->getChildNodes; # returns a NodeList (object reference)
for my $kid ($node->getChildNodes) # iterate over the children of $node
If I pass it in my function as below.
&myfunction($node->getChildNodes)
I am not getting the reference to the list.
Is there any way to get the reference with out declaring temporary scalar variable, like below.
my $tmp=$node->getChildNodes;
&myfunction($tmp)
Thank you.
myfunction([ $node->getChildNodes ])
myfunction(scalar $node->getChildNodes)
The second avoids creating a new array and a new reference, but the first might be clearer.
PS — Why are you telling Perl to ignore the prototype on myfunction? Don't use &.

How do I use a global variable in the same Mongodb script JS file

I have my JS file.
I have a variable declared at the top called:
var aCollection = db.myCollection;
I use this variable to refer to the collection. It's easy, since I can change the name of the collection to process another collection.
Now I want to use this in a function, like this:
fn1 = function(_id) {
// use _id and aCollection
// i get an error if I use "aCollection"
}
And I call the above function like this:
db.eval(fn1, "245");
db.eval executes fn1 on the server in a separate context so it doesn't have access to the global context of its containing script. You'd have to change fn1 to accept aCollection as a parameter and then pass that parameter into your db.eval call.