Hide selected layers only hides first layer then stops

A few more words to expand on what @Aerilius wrote: The basic flaw with your code is that all of the key variables are set when the code is loaded by Ruby. mod, ents, sel, all_lays, and sel_lays all have the values that were in place during the load. But the context menu callbacks occur later, when these values may no longer be valid. These variables have been defined at global scope, so they should persist, but even if they have not themselves been GC’d, they may point to entities that have been GC’d or that have been deleted or marked invalid by SketchUp. The selection, in particular, is not likely to be what you want - odds are it was empty when your code was loaded!

So, to fix it you need to read current values at the time the callbacks occur. This will require separate methods for handling the layers for all entities and for the current selection. For example,

def get_ents_layers()
  ents = SketchUp.active_model.entities
  get_layers(ents)
end

then

item 3=menu.add_item("Show all layers") {show_layers(get_ents_layers())}

For future reference, you should always wrap your own code in a module so that its namespace can’t collide with anything else in the global Ruby namespace. In your example, there is a danger that someone else may have defined things named mod, ents, sel, etc. and you will collide!