Git Product home page Git Product logo

Comments (7)

trxcllnt avatar trxcllnt commented on July 17, 2024

model.get(["genres",0,0,null]) current outputs "Die Hard". More specifically it outputs:

{ json: { genres: { "0": { "0": { "null": "Die Hard" } } } }

No it doesn't, it outputs:

{ json: { genres: { "0": { "0": "Die Hard" } } }

The current behavior has no valid use-cases. Developers are expected to request JSON when they are trying to create data they intend to show on-screen. Developers should never be displaying paths on screen. This is an anti-pattern, because it encourages developers to make display considerations when designing their path structures.

His dudeness, or uh, duder, or uh y'know, el duderino if you're not into the whole brevity thing

Here's an example:

<!DOCTYPE>
<html><head>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/rxjs/2.5.1/rx.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/rxjs-jquery/1.1.6/rx.jquery.js"></script>
<script type="text/javascript">
var haml = require("hamljs");
var falcor = require("falcor");
var Model = falcor.Model;
var template = haml.compile("\
  %ul.devs \
    - for dev in @devs \
      %li.dev \
        %a(href='#' + dev['more-info'].join('/')) = dev.name \
");
var teamListSelector = function (devs) {
  return template({
    devs: Object.keys(devs).sort().reduce(function (list, key) {
      list.push(devs[key]);
      return list;
    }, [])
  });
};
var employeeInfoTemplate = haml.compile("\
  %div.employee-info \
    %span.name = @name \
    is in %span.building = @building \
    on floor %span.floor = @floor
    at dest number \
    %span.desk = @desk \
");
var model = new Model({ cache: { "netflix": {
    "tvui-devs": {
        0: { "name": "Steve McGuire", "more-info": { "$type": "ref", ["netflix", "employees", "smcguire"] } },
        1: { "name": "Jerry Hamlet", "more-info": { "$type": "ref", ["netflix", "employees", "jhamlet"] } },
        2: { "name": "Ian McKay", "more-info": { "$type": "ref", ["netflix", "employees", "imckay"] } },
    },
    "falcor-devs": {
        0: { "name": "Jafar Husain", "more-info": { "$type": "ref", ["netflix", "employees", "jhusain"] } },
        1: { "name": "Paul Taylor", "more-info": { "$type": "ref", ["netflix", "employees", "ptaylor"] } },
        2: { "name": "Michael Paulson", "more-info": { "$type": "ref", ["netflix", "employees", "mpaulson"] } }
    },
    "employees": {
        "smcguire": { "building": "A", "floor": 3, "desk": 120 },
        "jhamlet": { "building": "A", "floor": 3, "desk": 121 },
        "imckay": { "building": "A", "floor": 3, "desk": 122 },
        "jhusain": { "building": "A", "floor": 3, "desk": 123 },
        "ptaylor": { "building": "A", "floor": 3, "desk": 124 },
        "mpaulson": { "building": "A", "floor": 3, "desk": 125 }
    }}}});

$(".teams a").clickAsObservable().
flatMap(function(e) {
  var teamPath = $(e.target).attr("href").substr(1).join("/");
  return model.bind(teamPath);
}).
flatMap(function(teamModel) {
  return teamModel.get([{ to: 2 }, ["name", "more-info"]], teamListSelector);
}).
flatMap(function(teamHTML) {
  $(".employees").replace(teamHTML).find(".dev a").clickAsObservable()
}).
flatMap(function(e) {
  var employeePath = $(e.target).attr("href").substr(1).join("/");
  return model.bind(employeePath);
}).
flatMap(function(employeeModel) {
  return employeeModel.get([["building", "floor", "desk"]], employeeInfoTemplate);
}).
subscribe(function(employeeHTML) {
  $(".employee-info").replace(employeeHTML);
});
</script></head><body>
  <ul class="teams">
    <li><a href="#netflix/tvui-devs">TVUI</a></li>
    <li><a href="#netflix/falcor-devs">Falcor</a></li>
  </ul>
  <ul class="employees"></ul>
  <div class="employee-info"></div>
</body></html>
  1. References are leaf values, and should be treated the same as any other leaf value when requested.
  2. Most References point to branch nodes, not leaf nodes (as in your example). Since it's illegal to request for branch nodes, the 80% case will be they do want the reference when they request for it.
  3. JSON is an output format, not a cult. Just because someone wants their data as JSON doesn't mean they're buying into the story of templating.

from falcor.

ThePrimeagen avatar ThePrimeagen commented on July 17, 2024

@jhusain Ill have to agree with @trxcllnt on this one. This seems to be more of an opinion.

Some points to consider.
I am a user, brand new to falcor. so i execute the following query.

model.get('someRefThatPointsToLeaf[0]').then(template.render);

They learn about the selector function. Super cool.

model.get('someRefThatPointsToLeaf[0]', function(x) { return x; }).then(template.render);

BOOM it breaks the template.


The key problem i have with this is that its not an output format problem, its a behavior problem. Falcor will fundamentally act different (not output different) by requesting different output. To me this should be sufficiently confusing.


There are also lots of logistical issues in the code with this change. I feel like we are hyper catering to the rookie. It is fundamental to falcor that you know about the data coming down. You don't have to know the IDs, you have to know the structure. -- Now i am just rambling.

from falcor.

ktrott avatar ktrott commented on July 17, 2024

It seems like an invalid request from a public API consumer to ask for "null" in the path.

It seems like we need "null" for internal implementation cases but not for public API. I don't understand the null in JSON responses at all. Why would an end user ever ask for or expect back null? Seems like an invalid request from a public API perspective.

from falcor.

ktrott avatar ktrott commented on July 17, 2024

Notes from Falcor meeting:
So we don't need null if its just about reporting, it's when we're taking the reported error message and trying to feed it back into invalidate.

How would the user know that they need to invalidate/remove the error vs. the reference itself?

@trxcllnt says in Falcor meeting:
With errors, sentinels, you would always want to invalidate the nodes in the cache instead of the references, but there are use cases where you want to invalidate references -- when you want to get fresh data from the server.

@michaelbpaulson We should either always hide references or never hide references, but not go halfsies.

Proposal from Falcor meeting (everyone in room is in agreement @trxcllnt, @michaelbpaulson, @sdesai, @ktrott00):
set(path, undefined) -> follows references in leaf position (today, we never follow reference in leaf position)
setReference(path, undefined) -> doesn't follow references in leaf position; allows invalidating a reference

This eliminates null from JSON Graph / paths entirely, which would be fantastic according to @trxcllnt and @michaelbpaulson. Cleans up the API quite a bit.

from falcor.

ktrott avatar ktrott commented on July 17, 2024

Falcor meeting (attendees: @jhusain, @sdesai, @michaelbpaulson, @trxcllnt, @ktrott00):

  • Agreed that JSON is a behavior change so should treat as a mode not an output format
  • Agreed that null is a rare case
  • Agreed that null is invalid path in JSON mode

Arguments against:

  • No way to get hierarchal w/ leaf references: What if I want a JSON tree but I want the reference for leaf nodes (don't want to follow the reference)
  • Should be a more explicit API around following or not following references. There's no need to distinguish between switching between graph or tree as your model.

Counter proposal:

  • You build your model w/ and w/o references and use get and set to work with it and have explicit separate getReference and setReference API. Problem with this approach: Batching gets broken by two separate APIs. Can't rely on asynchronity

from falcor.

jhusain avatar jhusain commented on July 17, 2024

The alternate proposal is here: #131

The proposal that includes special methods for references does not accommodate current requirements.

The most obvious deficiency is that it does not handle the call case. While get and set can rely on batching to ensure a getRef and get go together In a single request, calls cannot be batched because they are not idempotent. You could do a cal and a callRef because you could repeat side-effects. In other words the proposal above does not allow the retrieval of both refs and ref targets after a call is complete if you eliminate null.

Even if this proposal worked it would still violate one of Falcors previous guarantees: it is always possible to map a method call to an HTTP request. Batching will be common today, but we cant rely on it in the future. As soon as HTTP2 becomes ubiquitous the correct default for Falcor will be to run unbatched. HTTP2 will be much more efficient at batching requests and allow multiplexing of server results. This is why using batching to accomplish mainline scenarios like ensuring a set of data is retrieved in a single connection is ill-advised.

The alternate proposal maintains would introduce two Model modes: asJSON and asJSONGraph. The Model's default mode will be graph. These modes would create new Models, not mutate the existing one.

model.asTree().get("profiles[0..5].name")

In tree mode, all references are followed even if they are in found in the last key of the path. Sets behave the same way they would against a JSON object, replacing the target of a reference instead of the reference itself. This means that in tree mode the model will always emit JSON. In graph mode you can select references with paths, or select their target with a trailing null in the path. The null key will be aliased to a constant (REF_TARGET) for more readability. Note that null will only be necessary in the rare case in which references point to values.

This proposal can be clearly explained to developers using the same narrative we use to justify the JSON Graph language: JSON can't have refs. If you want to use a Graph, you go into Graph mode. If you want a tree, you will never see references.

Now that tree and graph moods are available, the model response output format options can be to just PathValue or Value. We've effectively separated the output format dimension from the behavior of whether the Model behaves like a tree or graph, which is a nice simplification.

Th only downside of this proposal is that references cannot appear in JSON. However if an application requires that refs not be transparent in a tree mode there is a workaround - introduce a key that contains the ref contents. I believe this wil not be a common-use case. If it comes up often, we could address to with a special constant in the last key (Model.REF).

from falcor.

ktrott avatar ktrott commented on July 17, 2024

Updated agreement: Leave as is for now and do nothing.

from falcor.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.