148

Is there a cleaner way to do something like this?

%w[address city state postal country].map(&:to_sym) 
#=> [:address, :city, :state, :postal, :country]

I would have figured %s would have done what I wanted, but it doesn't. It just takes everything between the brackets and makes one big symbol out of it.

Just a minor annoyance.

Deepak Mahakale
  • 22,834
  • 10
  • 68
  • 88
Drew
  • 15,158
  • 17
  • 68
  • 77
  • 1
    That's pretty standard. Is there anything about your implementation which makes this method undesirable? – dwhalen Sep 08 '11 at 21:57
  • 5
    Not "really" but Rails often has syntactical sugar like this that makes me feel all warm a tingly inside by using. :) – Drew Sep 09 '11 at 13:26
  • since ruby 2, there is ! see http://stackoverflow.com/questions/8816877/is-there-a-literal-notation-for-an-array-of-symbols – m_x Jan 26 '13 at 21:58
  • 1
    Possible duplicate of [Is there a literal notation for an array of symbols?](https://stackoverflow.com/questions/8816877/is-there-a-literal-notation-for-an-array-of-symbols) – ymoreau Aug 16 '18 at 10:12

3 Answers3

394

The original answer was written back in September '11, but, starting from Ruby 2.0, there is a shorter way to create an array of symbols! This literal:

%i[address city state postal country]

will do exactly what you want.

Dmitri
  • 2,658
  • 2
  • 25
  • 41
Joost Baaij
  • 7,538
  • 3
  • 32
  • 34
  • 5
    I always forget that it stands for "intern" an alternative to "to_sym". See http://www.codecademy.com/forum_questions/512a675cf116c52d0d00674b – A5308Y Jan 10 '14 at 15:44
  • Note the emphasis of ruby 2. This is not shown in Ruby Programming Language book because that only covers up to 1.9.3. – Donato Apr 23 '15 at 17:52
  • When using ruby's % literal syntax I prefer to use two non-alphanumeric characters in place of brackets, i.e. `%i|a b c|` – Epigene Oct 06 '15 at 10:31
  • 7
    Whilst this does what you want, anyone who sees this in your codebase will have to Google it to figure out what bizarro syntax Ruby has thrown at us this time. I highly recommend avoiding obscure language features when perfectly readable alternatives exist, i.e. [:address, :city, :state]. – Alex Aug 09 '16 at 05:48
  • @Epigene : please note that the Ruby style guide recommends using braces for array literals (%w, %i, %W, %I). Text between two pipe characters has a different meaning in Ruby. https://rubystyle.guide/#percent-literal-braces – Dmitri Oct 10 '19 at 17:02
  • 2
    @Alex : this is hardly an "obscure language feature" though maybe it was when you wrote your comment, but it is the accepted style now. https://rubystyle.guide/#percent-literal-braces – Dmitri Oct 10 '19 at 17:07
  • @Dmitri Yes, nowadays I use `%i[a b c]`, and `%w[a b c]` to make it obvious that the intended outcome object is an Array. – Epigene Oct 11 '19 at 08:30
101

With a risk of becoming too literal, I think the cleanest way to construct an array of symbols is using an array of symbols.

fields = [:address, :city, :state, :postal, :country]

Can't think of anything more concise than that.

Joost Baaij
  • 7,538
  • 3
  • 32
  • 34
  • 14
    Do you mean "too literal"? – Andrew Grimm Sep 08 '11 at 23:40
  • I always like finding and using the most powerful and concise ways of doing things. This answer is actually less keystrokes than mine for this particular list but with a list of ~9 or more items, an alternative would be shorter. Thanks for the answer. :) – Drew Sep 09 '11 at 13:30
  • 6
    I think readability trumps all in this case. This answer is a LOT more readable (IMO) than the %w/to_sym alternative. Don't make the next developer to take over your stuff want to punch you in the throat. – Bruce Hubbard Aug 05 '13 at 20:07
3

%i[ ] Non-interpolated Array of symbols, separated by whitespace (after Ruby 2.0)

%I[ ] Interpolated Array of symbols, separated by whitespace (after Ruby 2.0)

%i[address city state postal country]

the cleanest way to do this is:

%w[address city state postal country].map(&:to_sym)

askrynnikov
  • 657
  • 10
  • 15