Ruby hash equivalent of JavaScript's object initializer ES6 shorthand

前端 未结 5 504
心在旅途
心在旅途 2021-01-07 23:02

In JavaScript ES6 we can create objects where variable names become keys like this:

> let a = \'aaa\'
\'aaa\'

> let b = \'bbb\'
\'bbb\'

> { a, b }         


        
5条回答
  •  猫巷女王i
    2021-01-07 23:18

    Although Ruby / Rails doesn't yet support an equivalent to the ES6 shorthand syntax for hashes, there are a few handy idioms already that often come in handy.

    Ruby

    Consider the following method:

    def test_splat(a:, b:, c:)
      [a, b, c].inspect
    end
    

    test_splat(a: 4, b: 5, c: 6) yields "[4, 5, 6]"

    Although if you already have a hash such as hash = { a: 1, b: 2, c: 3 }, you can simply call it like this:

    test_splat(hash) which yields "[1, 2, 3]"

    Further

    If you have a sub_hash, you can use it alongside other kwargs using the kwarg splat operator **. For example if you have sub_hash = { a: 1, b: 2 }, calling:

    test_splat(sub_hash) yields ArgumentError: missing keyword: c

    and calling:

    test_splat(sub_hash, c: 3) yields ArgumentError: wrong number of arguments (given 1, expected 0)

    but using the splat operator **, you can do splat the sub_hash arg:

    test_splat(**sub_hash, c: 3) which yields "[1, 2, 3]"

    For more reading see https://www.justinweiss.com/articles/fun-with-keyword-arguments/

    Rails

    The above plus a few extra methods can come in handy for Rails users, particularly in controllers when params are passed in.

    Suppose you have an ActionController::Parameters object with more attributes than you need and you want a subset. E.g: { a: 1, b: 2, d: 4 }. The slice method on Hash is very handy here.

    First, permit your params:

    permitted_params = params.permit(:a, :b, :d).to_h.symbolize_keys.

    We add .to_h.symbolize_keys because ActionController::Parameters doesn't support symbolize_keys, and kwargs require the args' keys to be symbols, not strings. So the .to_h converts it to an ActiveSupport::HashWithIndifferentAccess, and the symbolize_keys converts the hash's keys from strings to symbols.

    Now, calling:

    test_splat(**permitted_params, c: 3) will yield ArgumentError: unknown keyword: d as expected since d isn't a kwarg for the test_splat method. Although using slice achieves what we want here:

    test_splat(**permitted_params.slice(:a, :b), c: 3) yields "[1, 2, 3]"

提交回复
热议问题