What's the prescribed way to mixin methods to underscore within your package without implying them?


#1

so you have a bunch of methods you have tacked on to underscore within your package:

_.mixin({
    foo: function() {},
    bar: function() {} //etc
});

but you don’t want to risk conflicting with the main application or other packages, what’s the best way to prevent that?

The 2 options I’m considering are adding a few underscores before my methods OR cloning underscore onto a different leading character, eg: U.foo, but when you clone it via:

U = _;
_.extend(U, _)

both U and _ get your methods.

Without adding additional code that will increase file size, what other options do I have?


#2

Can you do U = {..._}?

(just spitballing)


#3

_.extend({}, U, _) will return new object with both methods, but not mutate U nor _


#4

that actually results in only _ getting newly added methods.

that does the same as my original one, which is continue to put methods on both U and _.

To make it more clear, what I’m saying is that I want to never have my methods on _. So that means I must first create this clone of underscore on to a different variable, and then use only that to mixin new methods, and without the methods also going back to the original underscore object.

…I just found one hacky way to do it: go back to _ and delete the keys for all the methods you added after you cloned into a different variable. That way client code will never have them. …But that basically still has the same problem: instead of overwriting client underscore mixed-in methods, i might now deleted them! lol


#5

my “solution” does not add methods to any source objects, it just return object with them merged.
But it does not change source objects in any way.

Maybe I dont understand exactly what you are trying to accomplish.

U = ({}, _, myNewMethodsObject);
_ is still the same
and U have combination of both _ and all from myNewMethodsObject


#6

This is how I am doing this (yes coffeescript, use coffee2js on web if you want to see pure js).
Our productDetail package

@variableFeed = (shopFeed, currentAvailability) ->
  switch currentAvailability
    when 'in_stock' then return _.map(shopFeed, inStockFiltered)
    when 'in_store' then return _.map(shopFeed, inStockFiltered)
    else return shopFeed

@priceSort = (ascend = true) ->
  if ascend
    (x) -> x.price_vat
  else
    (x) -> -(x.price_vat)

# cloned _ (underscore) with package related mixins
@productDetail_ = _.extend({}, _)

productDetail_.mixin(
  variableFeed: variableFeed
  placementFeed: placementFeed
  uniqPlacement: uniqPlacement
)

these @functions are global - but as we dont export them from package, they dont polute global namespace
same with productDetail_ - cloned underscore with our mixins only available in this package

and than in helper

 'eshopDepots': ->
    instance = Template.instance()
    currentAvailability = instance.currentAvailability.get()._id
    currentSort = instance.currentPriceSort.get()._id

    # initial feed
    shopFeed = EshopDepots.find().fetch()
    
    # get all possible addresses
    allAddresses = productDetail_.chain(shopFeed)
      .placementFeed()
      .uniqPlacement()
      .value()

    # apply filters
    resultFeed = productDetail_.chain(shopFeed)
      .variableFeed(currentAvailability)
      .filter(pickAvailability(currentAvailability))
      .sortBy(priceSort(currentSort is 'najlacnejsie'))
      .value()

    # get filtered addresses
    filteredAddresses = productDetail_.chain(resultFeed)
      .placementFeed()
      .uniqPlacement()
      .value()

    # more messing with addresses

    return resultFeed

#7

sure, you can extend all the methods to wherever you want, but then you won’t get access to chaining. _ is more than just a dumb map of methods.


#8

yes, I already figured out that setting mixin for that cloned one affects also global _ :frowning:


#9

for now I am moving to wrapper like this

_.mixin(
  pipe: (stream, localFunction, args...) ->
    return localFunction(stream, args...)
)

and using it this way

  _.chain(addressList)
  .pipe(groupAddress, 'value1', 'value2')