can-connect
can-connect copied to clipboard
Enable modification of existing behavior chains
Goals:
- allow modification of existing can-connect behavior chains (via insertion and replacement)
API:
- newBehaviour.insertAfter(existingBehaviour, behaviourChain) where existingBehaviour is a 'behaviorName' string or behaviour mixin instance matching an existing behaviour in the prototype chain. .insertAfter returns a new connection with the modification made. eg.
import superMap from 'can-connect/can/super-map/';
import newBehaviour from './custom-behaviour/';
var connection = superMap(...);
connection = newBehaviour.insertAfter('data/callbacks', newBehaviour);
- newBehaviour.replace(existingBehaviour, behaviourChain) where existingBehaviour is a 'behaviorName' string or behaviour mixin instance matching an existing behaviour in the prototype chain. .replace returns a new connection with the modification made. eg.
import superMap from 'can-connect/can/super-map/';
import newBehaviour from './custom-behaviour/';
import dataCallbacks from 'can-connect/data/callbacks/';
var connection = superMap(...);
connection = newBehaviour.replace(dataCallbacks, newBehaviour);
This feels wrong to me, you should really be creating new connections rather than modifying an existing one. What is the use case to have a connection that gets modified later?
@matthewp my use case was the ability to use the predefined behaviour chain of can-connect/can/super-map with a replacement or additional behaviour without having to redefine the entire chain. However this could be accomplished by exposing the list of behaviours attached by superMap, creating a clone of superMap and then modifying the now-exposed list of behaviours directly.
Perhaps @justinbmeyer had another use case in mind where that might not be an acceptable solution?
@matthewcp yes, people asked for mixins that could be added to an existing connection. This would aid in that.
thanks for the clarification
@justinbmeyer I understand that people are asking for it. They are asking for it because creating your own connections is too hard. The solution is make creating connections not hard any more, not add helper methods so people can use superMap and insert stuff in the middle.
Why, that makes it easy. It's easy to understand a certain set of functionality and then add stuff to it. Starting with a base model, like baseMap is really convenient .
Sent from my iPhone
On May 24, 2017, at 6:34 PM, Matthew Phillips [email protected] wrote:
@justinbmeyer I understand that people are asking for it. They are asking for it because creating your own connections is too hard. The solution is make creating connections not hard any more, not add helper methods so people can use superMap and insert stuff in the middle.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
@matthewp (now that I'm back to my computer, a more thoughtful response)
I think I'm acknowledging that creating even a custom base connection would be rather difficult even with can-validate-interface. A basic CanJS connection looks like:
var connection = canMap( constructor( dataUrl( baseBehavior(options) ) ) );
base-map would look like:
var connection = callbacksOnce( realTime( dataParse( dataCallbacks( constructorStore( canRef( canMap( constructor( dataUrl( baseBehavior(options) ) ) ) ) ) ) ) ) );
The solution is make creating connections not hard any more, not add helper methods so people can use superMap and insert stuff in the middle.
The interface stuff and documentation improvements are designed to directly help making piece-by-piece connections. We are also open to other suggestions that would improve this specifically (I'm not aware of alternatives that don't break existing APIs). Even if there are other good suggestions, it doesn't mean this isn't a valid and useful suggestion. This isn't an either-or situation. It's a yes-and.
Fortunately, this can make creating your own connections easy. I can create a "simpleMap" behavior that makes sure canMap, constructor, and dataUrl are all added like:
var someBaseConnection = base({ ... });
var mapConnection = addSimpleMap( someBaseConnection )
If someone wants real-time, it can add constructorStore, realTime, callbacksOnce like:
var connection = addRealTime( mapConnection )
This functionality allows behaviors that mixin several behaviors at once ... collections of behaviors.
@bmomberger-bitovi wanted to make something like real-time automatically add constructorStore and callbacksOnce, but this broke the independence of these behaviors. I think it's important that someone can make a different constructorStore.
This functionality allows mixins that provide a bunch of other behaviors, ensure that the right mixins are present and add them if not.
I'm cool with this as long as these "middle level" mixins are created. I believe an end user shouldn't have to choose between high-level things like superMap and super low-level things like data/callbacks. You should be able to build your own connection without knowing about data/callbacks.
What are the mid-level mixins that are needed? I'll create issues for those.
I've added my notes from the most recent contributors meeting where this was discussed to a gist.