Victor Borshchov Victor Borshchov - 5 months ago 11
Ruby Question

Insert elements before/after certain element in array

I have method

header_components
and I want to create method
add_header_components
with behaviour like this:

add_header_components << :buttons, after: :logo #=> [:logo, :buttons, :user_name]
header_components #=> [:logo, :user_name]


This is what I try:

# this method just return the array
def header_components
[:logo, :user]
end

def add_header_components(name, *args)
h = header_components
options = args.extract_options!
if options.keys.include?(:after)
index = header_components.index(options[:after])
h = header_components.insert(index+1, name.to_s)
elsif options.keys.include?(:before)
index = header_components.index(options[:before])
h = header_components.insert(index, name.to_s)
end
h
end


this method works but I want pass more than one
name
parameter to method.

Another question:



If there any way to get the same array with this syntax:

header_components << :buttons, :search, after: :logo

Answer

Given that header_components is behaving like a variable, why not make it one? As for adding multiple headers at once, you can use the splat/double splat syntax:

class Foo
  attr_reader :header_components
  def initialize
    @header_components = ['logo', 'user']
  end

  def add_header_components(*headers, **options)
    if options.keys.include?(:after)
      index = @header_components.index(options[:after])
      @header_components.insert(index+1, *headers)
    elsif options.keys.include?(:before)
      index = @header_components.index(options[:before])
      @header_components.insert(index, *headers)
    else
      # I guess this should by default append all headers to the list?
     @header_components.concat headers
    end
  end
end

f = Foo.new
f.header_components # => ['logo', 'user']
f.add_header_components('hello', 'world', after: 'logo')
f.header_components # => ['logo', 'hello', 'world', 'user']
Comments