35 Matching Annotations
  1. Nov 2021
    1. Content in the wild can easily come to rely on this: var underAutomation = ("webdriver" in navigator) ? navigator.webdriver : false; v, without this behaviour: var underAutomation = navigator.webdriver;
  2. Sep 2021
  3. Aug 2021
  4. Jun 2021
  5. Mar 2021
    1. Coming from React to Svelte this did catch me out numerous times but for me I now prefer Svelte's approach, particularly because it removes some of the boilerplate around useEffect.
    2. Here's where I start to have a preference for Svelte; the two are very similar but once I got used to Svelte I found that React felt like jumping through hoops. You can't create a worker instance, it has to go in a useRef, and then you can't easily pull code out into a function without then requiring useCallback so it can be a safe dependency on useEffect. With Svelte I write code that's closer to "plain" JavaScript, whereas in React more of my code is wrapped in a React primitive.
    1. Pluggability uses the Loggability library. Just set the log level to 'debug' and it'll explain what's going on:
  6. Feb 2021
    1. To understand this helper, you should understand that every step invocation calls Output() for you behind the scenes. The following DSL use is identical to the one [above]. class Execute < Trailblazer::Activity::Railway step :find_provider, Output(Trailblazer::Activity::Left, :failure) => Track(:failure), Output(Trailblazer::Activity::Right, :success) => Track(:success)
    2. For branching out a separate path in an activity, use the Path() macro. It’s a convenient, simple way to declare alternative routes

      Seems like this would be a very common need: once you switch to a custom failure track, you want it to stay on that track until the end!!!

      The problem is that in a Railway, everything automatically has 2 outputs. But we really only need one (which is exactly what Path gives us). And you end up fighting the defaults when there are the automatic 2 outputs, because you have to remember to explicitly/verbosely redirect all of those outputs or they may end up going somewhere you don't want them to go.

      The default behavior of everything going to the next defined step is not helpful for doing that, and in fact is quite frustrating because you don't want unrelated steps to accidentally end up on one of the tasks in your custom failure track.

      And you can't use fail for custom-track steps becase that breaks magnetic_to for some reason.

      I was finding myself very in need of something like this, and was about to write my own DSL, but then I discovered this. I still think it needs a better DSL than this, but at least they provided a way to do this. Much needed.

      For this example, I might write something like this:

      step :decide_type, Output(Activity::Left, :credit_card) => Track(:with_credit_card)
      
      # Create the track, which would automatically create an implicit End with the same id.
      Track(:with_credit_card) do
          step :authorize
          step :charge
      end
      

      I guess that's not much different than theirs. Main improvement is it avoids ugly need to specify end_id/end_task.

      But that wouldn't actually be enough either in this example, because you would actually want to have a failure track there and a path doesn't have one ... so it sounds like Subprocess and a new self-contained ProcessCreditCard Railway would be the best solution for this particular example... Subprocess is the ultimate in flexibility and gives us all the flexibility we need)


      But what if you had a path that you needed to direct to from 2 different tasks' outputs?

      Example: I came up with this, but it takes a lot of effort to keep my custom path/track hidden/"isolated" and prevent other tasks from automatically/implicitly going into those steps:

      class Example::ValidationErrorTrack < Trailblazer::Activity::Railway
        step :validate_model, Output(:failure) => Track(:validation_error)
        step :save,           Output(:failure) => Track(:validation_error)
      
        # Can't use fail here or the magnetic_to won't work and  Track(:validation_error) won't work
        step :log_validation_error, magnetic_to: :validation_error,
          Output(:success) => End(:validation_error), 
          Output(:failure) => End(:validation_error) 
      end
      
      puts Trailblazer::Developer.render o
      Reloading...
      
      #<Start/:default>
       {Trailblazer::Activity::Right} => #<Trailblazer::Activity::TaskBuilder::Task user_proc=validate_model>
      #<Trailblazer::Activity::TaskBuilder::Task user_proc=validate_model>
       {Trailblazer::Activity::Left} => #<Trailblazer::Activity::TaskBuilder::Task user_proc=log_validation_error>
       {Trailblazer::Activity::Right} => #<Trailblazer::Activity::TaskBuilder::Task user_proc=save>
      #<Trailblazer::Activity::TaskBuilder::Task user_proc=save>
       {Trailblazer::Activity::Left} => #<Trailblazer::Activity::TaskBuilder::Task user_proc=log_validation_error>
       {Trailblazer::Activity::Right} => #<End/:success>
      #<Trailblazer::Activity::TaskBuilder::Task user_proc=log_validation_error>
       {Trailblazer::Activity::Left} => #<End/:validation_error>
       {Trailblazer::Activity::Right} => #<End/:validation_error>
      #<End/:success>
      
      #<End/:validation_error>
      
      #<End/:failure>
      

      Now attempt to do it with Path... Does the Path() have an ID we can reference? Or maybe we just keep a reference to the object and use it directly in 2 different places?

      class Example::ValidationErrorTrack::VPathHelper1 < Trailblazer::Activity::Railway
         validation_error_path = Path(end_id: "End.validation_error", end_task: End(:validation_error)) do
          step :log_validation_error
        end
        step :validate_model, Output(:failure) => validation_error_path
        step :save,           Output(:failure) => validation_error_path
      end
      
      o=Example::ValidationErrorTrack::VPathHelper1; puts Trailblazer::Developer.render o
      Reloading...
      
      #<Start/:default>
       {Trailblazer::Activity::Right} => #<Trailblazer::Activity::TaskBuilder::Task user_proc=validate_model>
      #<Trailblazer::Activity::TaskBuilder::Task user_proc=validate_model>
       {Trailblazer::Activity::Left} => #<Trailblazer::Activity::TaskBuilder::Task user_proc=log_validation_error>
       {Trailblazer::Activity::Right} => #<Trailblazer::Activity::TaskBuilder::Task user_proc=save>
      #<Trailblazer::Activity::TaskBuilder::Task user_proc=log_validation_error>
       {Trailblazer::Activity::Right} => #<End/:validation_error>
      #<Trailblazer::Activity::TaskBuilder::Task user_proc=save>
       {Trailblazer::Activity::Left} => #<Trailblazer::Activity::TaskBuilder::Task user_proc=log_validation_error>
       {Trailblazer::Activity::Right} => #<End/:success>
      #<End/:success>
      
      #<End/:validation_error>
      
      #<End/:failure>
      

      It's just too bad that:

      • there's not a Railway helper in case you want multiple outputs, though we could probably create one pretty easily using Path as our template
      • we can't "inline" a separate Railway acitivity (Subprocess "nests" it rather than "inlines")
    1. The sole purpose to add Dev::Trace::Inspector module is to make custom inspection possible and efficient while tracing. For example, ActiveRecord::Relation#inspect makes additional queries to fetch top 10 records and generate the output everytime. To avoid this, Inspector will not call inspect method when it finds such objects (deeply nested anywhere). Instead, it’ll call AR::Relation#to_sql to get plain SQL query which doesn’t make additional queries and is better to understand in tracing output.
    1. account.first_name = first_name if first_name.present? account.last_name = last_name if last_name.present?

      I guess this is needed so we don't reset to nil (erasing value in database) when they haven't even provided a new value as input.

      But surely there's a cleaner way...

  7. Dec 2020
  8. Oct 2020
    1. hyperscript is more concise because it's just a function call and doesn't require a closing tag. Using it will greatly simplify your tooling chain.

      I suppose this is also an argument that Python tries to make? That other languages have this con:

      • cons: closing tags make it more verbose / increase duplication and that Python is simpler / more concise because it uses indentation instead of closing delimiters like end or } ?
    1. Template literals work well for long embedded DSLs. Unfortunately the syntax noise is substantial when you exit in and out of embedded arbitrary ECMAScript expressions with identifiers in scope.
    1. But this is starting to become rather verbose at what could be a much simpler and more elegant solution if only there were another template helper that could do variable assignment.
    1. Comparison to useReducer
    2. This library is built in TypeScript, and for TypeScript users it offers an additional benefit: one no longer needs to declare action types. The example above, if we were to write it in TypeScript with useReducer, would require the declaration of an Action type: type Action = | { type: 'reset' } | { type: 'increment' } | { type: 'decrement' }; With useMethods the "actions" are implicitly derived from your methods, so you don't need to maintain this extra type artifact.
  9. Sep 2020
    1. It would be tiresome - and bloated - to include a class pass-through for every component or assigning custom properties (from the RFC linked) for all potential properties on every component, just in case it's gonna be used in layouts that requires it. Wrapping them in a wrapper div is certainly an option, but potentially creates 100s or 1000s (long lists, several lists etc.) of new elements in the DOM slowing down low-end devices.
    2. verbosity for multiple overrides in parent component markup
    3. variables and fallbacks in the child component css again seem verbose, and not as flexible as classes
    1. Your tooltip component will have to wrap your image with a span tag or something, it can’t just add events to its children. And if you are adding multiple actions to it you will have to wrap it multiple times.
      <Concern1> <Concern2> </Concern2> </Concern1>

      vs.

      <img use:concern1 use:concern2>

    1. Three tests to prove a small piece of behavior. Although it might seem overkill for such a small feature, these tests are quick to write—that is, once you know how to write them
  10. Aug 2020
  11. Jul 2020
    1. Take the case of the <input> element in this component — we could add an on:input event handler that sets the value of name to event.target.value, but it's a bit... boilerplatey
    1. Besides, this will just end up being reported as a security bug to the security list if left as is, cause docker will eat up all your disk space due to a single call site flooding STDERR forcing logs to grow forever.
  12. Jun 2020
    1. I was just expressing that, even thought I like React, I dread having to still manually handle everything, instead of just using a directive, a la Vue.JS. This is what I consider boilerplate. Hence my comment on how I could leave React for Svelte just because of that. Clearly a Svelte side-by-side code comparison shows a much cleaner code for Svelte.
    2. Man, just because it gets rid of SO MUCH boilerplate I want to switch already.It kills me everytime I work with forms in React. So much noise for such a simple task.