Попытка поместить результаты хэша в массив — Ruby on rails

#ruby-on-rails #ruby #arrays #hash

#ruby-on-rails #ruby #массивы #хэш

Вопрос:

Я только начинаю (надеюсь!) изучите программирование / ruby on rails и попытайтесь поместить результаты хэша в массив с помощью:

ApplicationController:

 def css_class
  css = Array.new
  product =  {@product.oil => ' oil', @product.pressure_meters => ' pressure_meters', @product.commercial => 'commercial'}
  product.each do |key, value| 
    if key == true
       css.push(value)
    end
  end
  сss.join
end
  

И это в ProductsController:

 def create
  @product = Product.new(params[:product])
  @product.css_class = css_class

  respond_to do |format|
    if @product.save
      format.html { redirect_to @product, notice: 'Product was successfully created.' }
      format.json { render json: @product, status: :created, location: @product }
    else
      format.html { render action: "new" }
      format.json { render json: @product.errors, status: :unprocessable_entity }
    end
  end
end
  

Кажется, что это сохраняет только последнее, что было помещено в массив, я попробовал приведенный ниже код самостоятельно, и, похоже, он работает, поэтому я озадачен тем, где я ошибаюсь?

 def css_class
  css = Array.new
  product =  {1 => ' pressure_meters', 2 => ' oil'}
  product.each do |key, value| 
    if key > 0
      css.push(value)
     end
  end
  css.join
end

puts css_class
  

Заранее спасибо.

Ответ №1:

В Ruby Hash не может быть дубликатов ключей, поэтому

 def css_class
  css = Array.new
  product = { @product.oil => ' oil', 
              @product.pressure_meters => ' pressure_meters', 
              @product.commercial => 'commercial' }
  product.each do |key, value| 
    if key == true
      css.push(value)
    end
  end
  сss.join
end
  

не сработает, потому что

 irb(main):0> h = { true => 'foo', true => 'bar', false=>'foo', false => 'bar' }
=> {true=>"bar", false=>"bar"}
  

ваш второй пример работает только потому, что у вас разные ключи (1,2) поэтому давайте немного переработаем ваш код

 def css_class
  css = ""
  product = { ' oil' => @product.oil, 
              ' pressure_meters' => @product.pressure_meters, 
              ' commercial' => @product.commercial }
  product.each do |key, value| 
    css << key  if value
  end

  сss.strip
end
  

это можно упростить еще больше, однако предыдущая версия тоже должна работать нормально

 def css_class
  [ "oil ", "pressure_meters ", "commercial " ].inject(""){ |sum, val| sum  = val if @product.send( val.strip ) }.strip
end
  

Ответ №2:

Вы можете использовать Hash#values для получения массива значений вашего хэша.

Итак:

 product_values = product.values
  

И условно, вы могли бы выбрать те, которые вы хотите использовать select , вот так:

 product_values = product.select {|k,v| k == true }.values
  

Который является подробным для:

 product_values = product.select {|k,v| k }.values
  

Комментарии:

1. Хэш в Ruby не может иметь повторяющихся ключей

2. Верно, я просто скопировал исходное условие. Я думаю, что удаление == true из исходного кода также решило бы проблему.

3. @alexhartley этот ответ намного лучше, чем ваш общепринятый ответ. для меня он более рубиновый.

Ответ №3:

Спасибо, что указали мне правильное направление. Я продолжал получать внутреннюю ошибку сервера 500 с вашим кодом Bohdan, не уверен почему, но поиграл с ней и в конечном итоге обнаружил, что это работает:

 def css_class
css = Array.new
   product = { ' oil' => @product.oil, 
            ' pressure_meters' => @product.pressure_meters, 
            ' commercial' => @product.commercial }
   product.each do |key, value| 
  css << key  if value 
end

  css.join
end