Home > OS >  Adding class to item in array based on it's value
Adding class to item in array based on it's value

Time:02-05

so I simply want to change the colour of the text of a list of arrays based on the word that's in the string.

Here's my array of combinations currently being outputted in the view with <%= @output %>:

[{"Mer lec sai ham"=>{:price=>13.1, :points=>53.4}}, {"Mer rus sai ham"=>{:price=>12.1, :points=>32.2}}, {"Fer rus sai ham"=>{:price=>13.1, :points=>31.4}}, {"Mcl rus sai ham"=>{:price=>13.5, :points=>14.9}}]

Here's my controller code:

# OUTPUT
    @output = ordered.map do |c|
      { c.join(" ")=>{ price: add_up(c, team_price, driver_price),
             points: add_dbl(c, team_points, driver_points).round(2)} }
    end

    @combo = @output.each do |p|
      if p = 'Mer'
        class_name = 'red'
      elsif p = 'lec'
        class_name = 'green'
      else
        class_name = 'black'
      end
    end

CSS:

.red{color:red;}
.green{color:green;}
.black{color:black;} 

And then I am just calling it in my view using <%= @combo %>

The ouput should be the list of combinations but this time just the words are coloured correctly. This is currently just showing nothing, it's not throwing errors though.

EDIT Added my full controller code in case it's needed:

# DEFINE VARIABLE AND TARGET
     teams = team_price.keys
     drivers = driver_price.keys
     target = 13.5

    # CREATE METHOD TO SUM BOTH PRICES AND POINTS FOR GIVEN COMBINATION
    def add_up(combo, ht, hd)
      t, d = combo
      ht[t]   hd.values_at(*d).sum
    end

    # METHOD TO DOUBLE HIGHEST DRIVER POINTS
    def add_dbl(combo, team_points, driver_points)
      t, ds = combo
      dmax = ds.max_by { |d| driver_points[d] }
      driver_points[dmax]   add_up(combo, team_points, driver_points)
    end

    # ALL POSSIBLE COMBINATIONS OF TEAM AND DRIVERS
    all_driver_combos = drivers.combination(3).to_a
    all_combos = teams.product(all_driver_combos)

    # SHOW ALL COMBOS WHERE SUM DOES NOT EXCEED TARGET
    valid_combos = all_combos.select do |c|
      add_up(c, team_price, driver_price) <= target
    end

    # SORT VALID COMBOS BY SUM OF POINTS FOR EACH ELEMENT
    ordered = valid_combos.sort_by do |c|
      -add_dbl(c, team_points, driver_points)
    end

    # SORT DRIVERS BY HIGHEST POINTS
    ordered.each do |_t,ds|
      ds.sort_by! { |d| -driver_points[d] }
    end

    # OUTPUT
    @output = ordered.map do |c|
      { c.join(" ")=>{ price: add_up(c, team_price, driver_price),
             points: add_dbl(c, team_points, driver_points).round(2)} }
    end

    @combo = @output.each do |p|
      if p = 'Mer'
        class_name = 'red'
      elsif p = 'lec'
        class_name = 'green'
      else
        class_name = 'black'
      end
    end

CodePudding user response:

Multiple problems:

  • you are using asignment (=) instead of comparison (==)
  • you are comparing (if you change it) a Hash to a string, which will never be true
  • you are assigning a local variable (class_name) which does not have an effect on the output
  • it seems you want to highlight each word with the color, not just the full sentence
  • you have an array of hashes, where the key is a "sentence" (at least multiple words) which you want to highlight seperately and the value is a hash again.

Here is something to get you started (first step is to get code working, next step would be to clean it up. E.g. moving things to helpers or components or decorators).

def whatever_action_this_is
  @output_with_colors = @output.map do |item|
    item.transform_keys do |key|
      words = key.split(' ')
      highlighted = words.map do |word|
        content_tag(:span, word, class: css_class(word))
      end
      highlighted.join(' ')
    end
  end
end

private

def css_class(word)
  case word.downcase
  when 'mer' then 'red'
  when 'lec' then 'green'
  else 'black'
  end
end

And then in your view, assuming some ERB template

<ul>
<% @output_with_colors.each do |item|
  <% item.each do |key, value|
    <li>
      <%= key.html_safe %>
      <br/>
      <%= value %>
    </li>
  <% end %>
<% end %>
</ul>

CodePudding user response:

It looks like you are using assignment (=) when you should be using comparison (==)?

@combo = @output.each do |p|
  if p = 'Mer'
    class_name = 'red'
  elsif p = 'lec'
    class_name = 'green'
  else
    class_name = 'black'
  end
end

Instead of

 @combo = @output.each do |p|
      if p == 'Mer'
        class_name = 'red'
      elsif p == 'lec'
        class_name = 'green'
      else
        class_name = 'black'
      end
    end

Also you are passing a hash as p and trying to compare it to a string. You don't need combo at all and should leave interface concerns out of your controller code. I would get rid of @combo. As far as stying things using CSS I try to keep it semantic. So I would name classes like:

.mer{color:red;}
.lec{color:green;}

And just leave black as the default.

Possible view code:

<% @output.each do |hash| %>
 <%= hash.keys.first.gsub(/Mer/, '<span >Lec</span>').gsub(/lec/, '<span >lec</span>') %>
  Price: <%= hash.values.first[:price] %>
  Points: <%= hash.values.first[:points] %>
<% end%>

This will wrap any word with a <span> tag that applies the color to that word based on the css defs. If "Lec" could appear as "Lec" or "lec" I would change the regexp in gsub to be case insensitive.

  • Related