Cycles in loops and assignment of variables in deep loop

I have such a block of code (this is a working version)

@full_user_schedule[0].attributes.each do |event_name, attending| if attending sessions_hash.each do |id, name| event_name = event_name.sub(name, id.to_s) if event_name.include? name end @user_schedule.merge!(event_name => attending) end end 

When I tried to set the event_id variable in the sessions_hash.each statement, I could not force it to be assigned outside this loop (I received a warning for an unknown variable). I would like to know why this is so, and how to get around it.

The following is an example of what was unsuccessful (an event, although the log showed that the variable was set correctly), I did not have access to it outside the loop in which it was created.

 @full_user_schedule[0].attributes.each do |event_name, attending| if attending sessions_hash.each do |id, name| event_id = event_name.sub(name, id.to_s) if event_name.include? name end @user_schedule.merge!(event_id => attending) end end 

I tried to explicitly return event_id , but exited the loop. What? I do not understand?

+4
source share
2 answers

A block is really a kind of anonymous function, so it has its own scope, but has access to variables in the surrounding areas.

Just initialize event_id before starting the block, making it an element of the parent method.

 event_id = nil @full_user_schedule[0].attributes.each do |event_name, attending| ... 
+4
source

In the second code example, event_id is created and assigned in the block passed to sessions_hash.each . It exists only inside this block and cannot be accessed from code outside the block. This is called an area.

In the first example, you assign event_name, which is defined in the block passed to @full_user_schedule[0].attributes.each , and the rest of the code is also contained in this block, so it is always in scope.

I donโ€™t understand what you are trying to do here, but it looks like this will work:

 @full_user_schedule[0].attributes.each do |event_name, attending| if attending sessions_hash.each do |id, name| event_id = event_name.sub(name, id.to_s) if event_name.include? name end @user_schedule.merge!(event_id => attending) end end 

I moved the line @user_schedule... so that it was in the same area as event_id

0
source

All Articles