228 Matching Annotations
  1. Last 7 days
    1. The absence of a method name here is per design: this object does only one thing, and hence what it does is reflected in the class name.
    1. There’s no additional logic from Trailblazer happening here. The function returns a well-defined hash which is passed as an argument to step.
    1. # Yes, you can use lambdas as steps, too! step ->(ctx, params:, **) { params.is_a?(Hash) }
    2. Keyword arguments allow to define particular parameters as required. Should the parameter be missing, they also provide a way to set a default value. This is all done with pure Ruby.
  2. Feb 2021
    1. Please note that the actual task doesn’t have to be a proc! Use a class, constant, object, as long as it exposes a #call method it will flow.
    2. You may use keyword arguments in your filters for type safety and better readable code.
    1. Operations define the flow of their logic using the DSL and implement the particular steps with pure Ruby.
    1. Yes, Trailblazer is adding new abstractions and concepts and they are different to the 90s-Ruby, but now, at the latest, it becomes obvious how this improves the developing process. We’re no longer talking in two-dimensional method stack traces or byebug hoops, the language and conception is changing to the actual higher level code flow, to activities sitting in activities structured into smaller step units.
    1. There are times where it is useful to know whether a value was passed to run or the result of a filter default. In particular, it is useful when nil is an acceptable value.

      Yes! An illustration in ruby:

      main > h = {key_with_nil_value: nil}
      => {:key_with_nil_value=>nil}
      main > h[:key_with_nil_value]
      => nil
      main > h[:missing_key]  # this would be undefined in JavaScript (a useful distinction) rather than null, but in Ruby it's indistinguishable from the case where a nil value was actually explicitly _supplied_ by the caller/user
      => nil
      # so we have to check for "missingness" ("undefinedness"?) differently in Ruby
      main > h.key?(:key_with_nil_value)
      => true
      main > h.key?(:missing_key)
      => false

      This is one unfortunate side effect of Ruby having only nil and no built-in way to distinguish between null and undefined like in JavaScript.

    1. The problem is that you what you want is actually not de-structuring at all. You’re trying to go from 'arg1', { hash2: 'bar', hash3: 'baz' }, { hash1: 'foo' } (remember that 'arg1', foo: 'bar' is just shorthand for 'arg1', { foo: 'bar' }) to 'arg1', { hash1: 'foo', hash2: 'bar', hash3: 'baz' } which is, by definition, merging (note how the surrounding structure—the hash—is still there). Whereas de-structuring goes from 'arg1', [1, 2, 3] to 'arg1', 1, 2, 3
    1. {a: 1, b: 2, c: 3, d: 4} => {a:, b:, **rest} # a == 1, b == 2, rest == {:c=>3, :d=>4}

      equivalent in javascript:

      {a, b, ...rest} = {a: 1, b: 2, c: 3, d: 4}

      Not a bad replacement for that! I still find javascript's syntax a little more easily readable and natural, but given that we can't use the same syntax (probably because it would be incompatible with existing syntax rules that we can't break for compatibility reasons, unfortunately), this is a pretty good compromise/solution that they've come up with.

    2. You can rescue at the method level, but more likely you’d want to rescue at the statement level.
    3. (Yay for the hashrocket resurgence!)
    4. we’re going to look how improved pattern matching and rightward assignment make it possible to “destructure” hashes and arrays in Ruby 3—much like how you’d accomplish it in, say, JavaScript
    1. Nevermind, I use now reform-rails
    2. @adisos if reform-rails will not match, I suggest to use: https://github.com/orgsync/active_interaction I've switched to it after reform-rails as it was not fully detached from the activerecord, code is a bit hacky and complex to modify, and in overall reform not so flexible as active_interaction. It has multiple params as well: https://github.com/orgsync/active_interaction/blob/master/spec/active_interaction/modules/input_processor_spec.rb#L41

      I'm not sure what he meant by:

      fully detached from the activerecord I didn't think it was tied to ActiveRecord.

      But I definitely agree with:

      code is a bit hacky and complex to modify

    3. you can do pairs.each_with_object({}) do |(multiparameter_name, value), attributes|
    4. values_with_empty_parameters.each_value.all?(&:nil?) This comment has been minimized. Show comment Hide comment Copy link Quote reply egilburg on Apr 9, 2015 Contributor you can do values_with_empty_parameters.values.none? [nil, nil].none? => true Pick your reaction egilburg on Apr 9, 2015 Contributor you can do values_with_empty_parameters.values.none? [nil, nil].none? => true
    1. Set your models free from the accepts_nested_attributes_for helper. Action Form provides an object-oriented approach to represent your forms by building a form object, rather than relying on Active Record internals for doing this.

      It seems that the primary/only goal/purpose was to provide a better alternative to ActiveRecord's accepts_nested_attributes_for.

      Unfortunately, this appears to be abandoned.

    1. Set your models free from the accepts_nested_attributes_for helper. Active Form provides an object-oriented approach to represent your forms by building a form object, rather than relying on Active Record internals for doing this.
  3. Jan 2021
  4. Dec 2020
    1. Terminal Apps The Easy Way

      A ruby toolkit for building terminal apps. Components for handling common (and uncommon) needs.

    1. json.(

      I don't care what the Rubocop style guide says about this; this is nicer and cleaner than typing json.call(...).

  5. Nov 2020
  6. Oct 2020
    1. Probably wouldn't work for capybara-based tests where it forks a different process for the web server?

    1. However, if perform was creating threads and you ended up with closures inside perform, then you could end up with several threads referencing the same local variables captured through the closures. So you do have to be careful about scope issues when you create threads but you don't have to worry about it when dealing with simple methods that only work with local variables

      Однако, если выполнение создавало потоки, и вы закончили с замыканиями внутри выполнения, тогда вы могли бы получить несколько потоков, ссылающихся на одни и те же локальные переменные, захваченные с помощью замыканий. Таким образом, вы должны быть осторожны с проблемами области при создании потоков, но вам не нужно беспокоиться об этом при работе с простыми методами, которые работают только с локальными переменными.

    2. The local variables, such as your hash, are local to the particular invocation of the surrounding method. If two threads end up calling perform at the same time, then each call will get its own execution context and those won't overlap unless there are shared resources involved: instance variables (@hash), class variables (@@hash), globals ($hash), ... can cause concurrency problems. There's nothing to worry about thread-wise with something simple like your perform.

      Локальные переменные, такие как ваш хэш, являются локальными для конкретного вызова окружающего метода. Если два потока вызывают выполнение одновременно, то каждый вызов получит свой собственный контекст выполнения, и они не будут перекрываться, если не задействованы общие ресурсы: переменные экземпляра (@hash), переменные класса (@@ hash), глобальные переменные. ($ hash), ... может вызвать проблемы параллелизма. Не нужно беспокоиться о потоковой передаче с чем-то простым, например, с вашей работой.

  7. Sep 2020
  8. Aug 2020
    1. Ruby is the programming language used in Translation Proxy. For Sarah, Object Oriented Design “done the Ruby way” is so enjoyable and is the part of her work that she likes most.
  9. Jul 2020
    1. Ruby has some really nice libraries for working with linked data. These libraries allow you to work with the data in both a graph and resource-oriented fashion, allowing a developer to use the techniques that best suit his or her use cases and skills.
    1. Since Ruby 1.9.2, Time implementation uses a signed 63 bit integer, Bignum or Rational. The integer is a number of nanoseconds since the Epoch which can represent 1823-11-12 to 2116-02-20. When Bignum or Rational is used (before 1823, after 2116, under nanosecond), Time works slower as when integer is used.
    1. There is a usability problem here, it's basically impossible to read the output of Time#inspect in such a case, even though the input was readable.
    2. So, which is better? t.inspect # => "2007-11-01 15:25:00 8483885939586761/68719476736000000 UTC" t.inspect # => "2007-11-01 15:25:00.123456789000000004307366907596588134765625 UTC"
    1. Introducing Module#const_source_locationUsing Method#source_location made finding the location of any method fairly easy. Unfortunately, there wasn’t an equivalent for constants. This meant that unless the constant you needed to find was defined in your codebase, finding its source location was not easy.
    1. Enumerable#tally is added. It counts the occurrence of each element. ["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
    2. Enumerator::Lazy#eager is added. It generates a non-lazy enumerator from a lazy enumerator.
    3. A beginless range is experimentally introduced. It might not be as useful as an endless range, but would be good for DSL purposes.
    1. It does change it, but it makes it much simpler in my opinion. It is basically "the receiver is statically the explicit literal special variable self or implicit." This gets rid of the current exception for private writer methods (self.foo = bar).
    1. Why don't you allow a range without end, like (1..)? There are two advantages. First, we can write ary[1..] instead of ary[1..-1]. The -1 is one of the most I dislike in Ruby. It is very magical, ugly, redundant, and disappointing. I envy Python's ary[1:]. I know that ary.drop(1) is slightly fast, but too long for such a common operation, IMO. Second, we can write (1..).each {|n| ... }.
    1. require 'set' class Array def uniq_elements(&prc) prc ||= ->(e) { e } uniques, dups = {}, Set.new each do |e| k = prc[e] ((uniques.key?(k)) ? (dups << k; uniques.delete(k)) : uniques[k] = e) unless dups.include?(k) end uniques.values end end
    1. To me the difference between [1,1,2,2,3,3] and [1,2,3] is not []
    2. It’s even worse that there’s no alternative method that does the unsurprising thing IMO.
    3. Are you angry now? Because I’m angry.
    4. You should see me doing a write up for a Ruby feature suggestion only to discover that Array#- is hijacked for non-mathematical reasons
    5. Oh. Oh no. That's... not a thing that should be. People wonder why we can't get be more popular with science / math academics.
    6. I don't think this is a good overload of 'subtraction'1Olivier Lacan@olivierlacan·Jan 14, 2019Yup. I don’t either.
    7. but not as two methods called Array#- and Array#difference. As something like Array#set_difference maybe, or even Array#subtract_all, maybe.
    1. One may expect Array#- to behave like mathematical subtraction or difference when it doesn't. One could be forgiven to expect the following behavior: [1,1,2,2,3,3,4,4] - [1,2,3,4] => [1,2,3,4]
    2. I'll freely admit I was surprised by this behavior myself since I needed to obtain an Array with only one instance of each item in the argument array removed.
    1. If you answer is yes, then we are doing this wrong because subset? or part_of method should be in a parent class (maybe Enumerable class ) in order for it to work for subset, array, hash and any data structure that inherit from it Enumerable.
    1. Arrays are not sets. Trying to treat them as if they are is an error, and will create subtle problems. What should be the result of the following operations? [1, 1] | [1] [1] | [1, 1] Of course, there are more interesting examples. These two are to get you started. I don't care what the results currently are. I don't care what you think they should be. I can present extremely strong arguments for various answers. For this reason, I believe that #| is an ill-defined concept. Generalizing an ill-defined concept is a world of pain. If you insist on treating objects of one class as if they were members of a different class, there should be bumps in the road to at least warn you that maybe this is a bad idea. I'm not going to argue that we should remove or deprecate #|. I don't think of myself as a fanatic. But encouraging this sort of abuse of the type system just creates problems.
    2. I do not understand why concat modify the array, as most of the method of the Array class has a ! method for that. Should I also introduced a concat! method?
  10. Jun 2020
    1. What would be nice is if JavaScript had a built-in way to do what I can do in Ruby with:

      > I18n.interpolate('Hi, %{name}', name: 'Fred')
      => "Hi, Fred"

      But to be fair, I18n comes from i18n library, so JS could just as easily (and I'm sure does) have a library that does the same thing.

      Update: Actually, you can do this in plain Ruby (so why do we even need I18n.interpolate?):

      main > "Hi, %{name}" % {name: 'Fred'}
      => "Hi, Fred"
      main > ? String#%
      From: string.c (C Method):
      Owner: String
      Visibility: public
      Signature: %(arg1)
      Number of lines: 9
      Format---Uses str as a format specification, and returns the result
      of applying it to arg. If the format specification contains more than
      one substitution, then arg must be an Array or Hash
      containing the values to be substituted. See Kernel::sprintf for
      details of the format string.
         "%05d" % 123                              #=> "00123"
         "%-5s: %016x" % [ "ID", self.object_id ]  #=> "ID   : 00002b054ec93168"
         "foo = %{foo}" % { :foo => 'bar' }        #=> "foo = bar"

      I guess that built-in version is fine for simple cases. You only need to use I18n.translate if you need its more advanced features like I18n.config.missing_interpolation_argument_handler.

  11. May 2020
    1. However, distributing such Ruby apps to inexperienced end users or non-Ruby-programmer end users is problematic. If users have to install Ruby first, or if they have to use RubyGems, they can easily run into problems. Even if they already have Ruby installed, they can still run into problems, e.g. by having the wrong Ruby version installed. The point is, it's a very real problem that could harm your reputation.
    1. Programming languages These will probably expose my ignorance pretty nicely.

      When to use different programming languages (advice from an Amazon employee):

      • Java - enterprise applications
      • C# - Microsoft's spin on Java (useful in the Microsoft's ecosystem)
      • Ruby - when speed is more important then legibility or debugging
      • Python - same as Ruby but also for ML/AI (don't forget to use type hinting to make life a little saner)
      • Go/Rust - fresh web service where latency and performance were more important than community/library support
      • Haskell/Erlang - for very elegant/mathematical functional approach without a lot of business logic
      • Clojure - in situation when you love Lisp (?)
      • Kotlin/Scala - languages compiling to JVM bytecode (preferable over Clojure). Kotlin works with Java and has great IntelliJ support
      • C - classes of applications (operating systems, language design, low-level programming and hardware)
      • C++ - robotics, video games and high frequency trading where the performance gains from no garbage collection make it preferable to Java
      • PHP/Hack - testing server changes without rebuilding. PHP is banned at Amazon due to security reasons, but its successor, Hack, runs a lot of Facebook and Slack's backends
  12. Apr 2020
    1. The method name is generated by replacing spaces with underscores. The result does not need to be a valid Ruby identifier though, the name may contain punctuation characters etc. That's because in Ruby technically any string may be a method name. This may require use of define_method and send calls to function properly, but formally there's little restriction on the name.
    1. But where is the helper method defined? What’s its visibility? Can I put it in a module? Can I use inheritance? Who can call it? Can I call super from the extracted method? If so, where does super go?