jontly
jontly

Reputation: 238

Pass a Rails variable into a case statement

I'm using Rails and have an array that I'm looking to control the output of.

In short, if a project with an ID exists in @projects, then I don't want to output the corresponding part of the array, if that exists. So if a project with ID of 1 exists, then I don't want to output @array[1], even if that's present.

The following hardcoded case statement works successfully, to avoid outputting @array[1], @array[2] and @array[3]:

@array.each do |key, value|
  case key when '1','2','3' then
    next # Skip this array key
  end
  # Otherwise, do something else
end

But instead of hardcoding '1','2','3', I actually want these to be passed in dynamically, via ActiveRecord. i tried to build a string:

@projects_string = @projects.map {|element|
  "'#{element.id}'"
}.join(',')

This outputs successfully as '1','2','3'. But I can't figure out a way to pass this into the case statement. This fails to match:

@array.each do |key, value|
  case key when "#{@projects_string}" then
    next # Skip this array key
  end
  # Otherwise, do something else
end

Is there a way to achieve this using this method, or maybe a better way to achieve this using some of Rails' capabilities?

I did look through this answer, which seemed most relevant, but couldn't see how to implement it.

Upvotes: 0

Views: 507

Answers (4)

jstim
jstim

Reputation: 2432

I feel like this depends on the type of collection you are dealing with: Array or ActiveRelation.

If they are just arrays and you want elements of @array that aren't in @parent, you can just do:

@array - @parent

If they are both ActiveRecord objects, why not just filter out the @array when it's created?

@array = Project.where.not(id: @projects.pluck(:id))

It seems inefficient (n^2) to have to scan a lookup array (@projects) for each element in the collection you are iterating over.

Upvotes: 1

SreekanthGS
SreekanthGS

Reputation: 988

You can try the following:

@array = [1,2,3,4]
@projects = [2,3]
@array.each do |key|
  case
  when true === @projects.include?(key)
    next
  end
  puts "Doing something else for #{key}"
end

Outputs:

Doing something else for 1
Doing something else for 4

Upvotes: 0

Abdul Baig
Abdul Baig

Reputation: 3721

You should not use string but use array and do like

@array = Array.new
@array = @projects.map{|arr| arr.id}

@array.each do |key, value|
  if @array.include?(key)
    #code to skip if project is included
  else
    #your code
  end
end

Array can be used easily for comparisons than string

Upvotes: 1

Bachan Smruty
Bachan Smruty

Reputation: 5734

You can do it in this way as well.

@project_arr = @projects.map{|p| p.id.to_s}

@array.each do |key, value|
  unless @project_arr.include?(key.to_s)
    #YOUR CODE GOES HERE
  else
    # SKIP IT
  end
end

Upvotes: 1

Related Questions