【Rails6】mappingを使用した診断機能

## 1. 導入
### 背景
Railsアプリケーションでユーザー入力に基づく診断機能を実装する方法を説明します。本記事では、ユーザーの名前と選択したシナリオに応じて、最適な花を推薦する機能に焦点を当てています。
### 目的
この機能を通じて、特定の条件に基づいて適切なデータをマッピングし、ユーザーに適した結果を提示する方法を示します。

## 2. 実装手順
### 基本設定
- Railsアプリケーションのセットアップ
- 必要なGemのインストール（例: gem 'sqlite3', gem 'puma'）

<b>モデルの作成</b>
```ruby:ruby
# app/models/flower.rb
class Flower < ApplicationRecord
end
```

### コントローラの設定
```ruby:ruby
class DiagnosesController < ApplicationController
  def create
    @recipient_name = params[:recipient_name].strip.downcase
    @scene = params[:scene]
    @image_color = params[:image_color]
    flower_ids = @recipient_name.chars.map do |char|
      flower = char_to_flower(char, @scene, @image_color)
      flower.id if flower.present?
    end.compact
    redirect_to result_diagnoses_path(flower_ids: flower_ids.join(','))
  end

  private

  def char_to_flower(char, scene, color)
    # 花のマッピングロジックをここに記述
  end
end
```

### ビューの設定
```ruby:erb
<!-- app/views/diagnoses/show.html.erb -->
<%= @flower.name %>
<%= image_tag(@flower.image_url) %>
```

### ルーティングの設定
```ruby:ruby
# config/routes.rb
Rails.application.routes.draw do
  resources :diagnoses, only: [:create, :show]
end
```

## 3. マッピングロジックの詳細
```ruby:ruby
def char_to_flower(char, scene, color)
  mapping = {
    'birthday' => {
      'red' => { 'a' => 'Amaranthus', 'b' => 'Begonia', ... },
      ...
    },
    ...
  }
  flower_name = mapping.dig(scene, color, char.downcase) || 'Rose'
  Flower.find_by(name: flower_name)
end
```
私の場合、「誕生日」や「記念日」、イメージカラーによって出力される花を変更したかったので、以下のように記述しました。
```ruby:ruby
def char_to_flower(char, scene, color)
    mapping = {
      'birthday' => {
        'red' => {
          'a' => 'Amaranthus',
          'b' => 'Anthurium',
          'c' => 'Carnation',
          'd' => 'Dahlia',
          'e' => 'Echinacea',
          'f' => 'Freesia',
          'g' => 'Geranium',
          'h' => 'Hibiscus',
          'i' => 'Impatiens',
          'j' => 'Jasmine',
          'k' => 'Kalanchoe',
          'l' => 'Lobelia',
          'm' => 'Marigold',
          'n' => 'Nasturtium',
          'o' => 'Oleander',
          'p' => 'Poppy',
          'q' => 'Quince',
          'r' => 'Rose',
          's' => 'Salvia',
          't' => 'Tulip',
          'u' => 'Umbrella Plant',
          'v' => 'Verbena',
          'w' => 'Waxflower',
          'x' => 'Xeranthemum',
          'y' => 'Yucca',
          'z' => 'Zinnia'
        },
        'blue' => {
          'a' => 'Agapanthus',
          'b' => 'Bluebell',
          'c' => 'Cornflower',
          'd' => 'Delphinium',
          'e' => 'Eryngium',
          'f' => 'Forget-me-not',
          'g' => 'Gentian',
          'h' => 'Hydrangea',
          'i' => 'Iris',
          'j' => 'Jacaranda',
          'k' => 'Kangaroo Paw Blue',
          'l' => 'Larkspur',
          'm' => 'Morning Glory',
          'n' => 'Nigella',
          'o' => 'Oxalis',
          'p' => 'Plumbago',
          'q' => 'Queen’s Lace',
          'r' => 'Russian Sage',
          's' => 'Salvia Blue',
          't' => 'Thistle',
          'u' => 'Ultramarine Aster',
          'v' => 'Violet',
          'w' => 'Windflower',
          'x' => 'Xerophyllum',
          'y' => 'Yarrow Blue',
          'z' => 'Zephyranthes'
        },
        'yellow' => {
          'a' => 'Acacia',
          'b' => 'Buttercup',
          'c' => 'Coreopsis',
          'd' => 'Daffodil',
          'e' => 'Evening Primrose',
          'f' => 'Forsythia',
          'g' => 'Goldenrod',
          'h' => 'Helianthus',
          'i' => 'Inula',
          'j' => 'Jerusalem Artichoke',
          'k' => 'Kerria',
          'l' => 'Laburnum',
          'm' => 'Marigold',
          'n' => 'Narcissus',
          'o' => 'Oenothera',
          'p' => 'Primrose',
          'q' => 'Quince Yellow',
          'r' => 'Rudbeckia',
          's' => 'Sunflower',
          't' => 'Tickseed',
          'u' => 'Ulex',
          'v' => 'Verbascum',
          'w' => 'Wallflower',
          'x' => 'Xanthoceras',
          'y' => 'Yarrow Yellow',
          'z' => 'Zantedeschia'
        }
      },
      'anniversary' => {
        'red' => {
          'a' => 'Anemone',
          'b' => 'Begonia',
          'c' => 'Calla Lily',
          'd' => 'Dianthus',
          'e' => 'Euphorbia',
          'f' => 'Flamingo Flower',
          'g' => 'Gerbera',
          'h' => 'Hollyhock',
          'i' => 'Ixora',
          'j' => 'Jatropha',
          'k' => 'Kniphofia',
          'l' => 'Lantana',
          'm' => 'Mandevilla',
          'n' => 'Nerium',
          'o' => 'Orchid',
          'p' => 'Poinsettia',
          'q' => 'Quince',
          'r' => 'Ranunculus',
          's' => 'Salvia',
          't' => 'Torch Lily',
          'u' => 'Urceolina',
          'v' => 'Viburnum',
          'w' => 'Weigela',
          'x' => 'Xeronema',
          'y' => 'Yucca',
          'z' => 'Zephyranthes'
        },
    
        'blue' => {
          'a' => 'Aconitum',
          'b' => 'Blue Daisy',
          'c' => 'Clematis',
          'd' => 'Delphinium',
          'e' => 'Evolvulus',
          'f' => 'Felicia',
          'g' => 'Globularia',
          'h' => 'Hyacinth',
          'i' => 'Iris',
          'j' => 'Jasione',
          'k' => 'Kalmia',
          'l' => 'Lobelia',
          'm' => 'Myosotis',
          'n' => 'Nemophila',
          'o' => 'Omphalodes',
          'p' => 'Plumbago',
          'q' => 'Queen’s Lace',
          'r' => 'Russian Sage',
          's' => 'Scabiosa',
          't' => 'Trachelium',
          'u' => 'Utricularia',
          'v' => 'Veronica',
          'w' => 'Wahlenbergia',
          'x' => 'Xerophyllum',
          'y' => 'Yucca',
          'z' => 'Zephyranthes'
        },
        'yellow' => {
          'a' => 'Allamanda',
            'b' => 'Black-eyed Susan',
            'c' => 'Coreopsis',
            'd' => 'Dahlia',
            'e' => 'Evening Primrose',
            'f' => 'Freesia',
            'g' => 'Goldenrod',
            'h' => 'Helianthus',
            'i' => 'Inula',
            'j' => 'Jerusalem Artichoke',
            'k' => 'Kerria',
            'l' => 'Lantana',
            'm' => 'Marigold',
            'n' => 'Narcissus',
            'o' => 'Oenothera',
            'p' => 'Potentilla',
            'q' => 'Quince',
            'r' => 'Rudbeckia',
            's' => 'Sunflower',
            't' => 'Trollius',
            'u' => 'Ulex',
            'v' => 'Verbascum',
            'w' => 'Witch Hazel',
            'x' => 'Xyris',
            'y' => 'Yarrow',
            'z' => 'Zinnia'
        }
      }
    }
    
    default_flower = 'Rose' # デフォルトの花
  flower_name = mapping.dig(scene, color, char.downcase) || default_flower
  flower = Flower.find_by(name: flower_name)

  if flower_name == default_flower
    Rails.logger.debug "Default flower used for char: '#{char}', Scene: '#{scene}', Color: '#{color}'"
  else
    Rails.logger.debug "Mapped char: '#{char}' to flower: '#{flower_name}', Scene: '#{scene}', Color: '#{color}'"
  end

  flower
end
```
## Seedファイルの設定
- 花のデータの準備: 各花に対する名前、説明、そして任意で画像のファイル名を準備します。
- データの挿入: find_or_create_by メソッドを使用して、重複データが生成されないようにしながら花のデータをデータベースに挿入します。

```ruby:seeds.rb
flowers_data = [
  { name: 'Amaranthus', description: 'Vivid and colorful with long lasting flowers.', image_url: 'amaranthus.jpg' },
  { name: 'Anthurium', description: 'Known for its shiny red spathes and tropical foliage.', image_url: 'anthurium.jpg' },
  { name: 'Carnation', description: 'Symbol of love, fascination, and distinction.', image_url: 'carnation.jpg' },
  { name: 'Dahlia', description: 'Stunning symmetry and vibrant colors dominate this flower.', image_url: 'dahlia.jpg' },
  { name: 'Echinacea', description: 'Not only beautiful but also medicinal.', image_url: 'echinacea.jpg' },
  { name: 'Freesia', description: 'Highly aromatic and a wide range of colors.', image_url: 'freesia.jpg' },
  { name: 'Geranium', description: 'Popular for its bright and uplifting flowers.', image_url: 'geranium.jpg' },
  { name: 'Hibiscus', description: 'Large blooms make a decorative addition to home gardens.', image_url: 'hibiscus.jpg' },
  { name: 'Impatiens', description: 'Bright and cheerful flowers, thriving in almost any environment.', image_url: 'impatiens.jpg' },
  { name: 'Jasmine', description: 'Fragrant blooms that are often used in perfumes.', image_url: 'jasmine.jpg' },
  { name: 'Kalanchoe', description: 'A succulent with clusters of tiny flowers.', image_url: 'kalanchoe.jpg' },
  { name: 'Lobelia', description: 'Vivid blue flowers perfect for hanging baskets.', image_url: 'lobelia.jpg' },
  { name: 'Marigold', description: 'Golden, orange, yellow, and white colors, a symbol of passion and creativity.', image_url: 'marigold.jpg' },
  { name: 'Nasturtium', description: 'Edible flowers with a peppery flavor.', image_url: 'nasturtium.jpg' },
  { name: 'Oleander', description: 'Beautiful but toxic, great for landscaping.', image_url: 'oleander.jpg' },
  { name: 'Poppy', description: 'Symbol of remembrance, with delicate, papery petals.', image_url: 'poppy.jpg' },
  { name: 'Quince', description: 'Bright spring flowers and a harbinger of the warm season.', image_url: 'quince.jpg' },
  { name: 'Rose', description: 'A symbol of love and passion.', image_url: 'rose.png' },
  { name: 'Salvia', description: 'Striking blooms and aromatic foliage.', image_url: 'salvia.jpg' },
  { name: 'Tulip', description: 'Classic spring flower with bold colors and elegant shape.', image_url: 'tulip.jpg' },
  { name: 'Umbrella Plant', description: 'Tropical foliage plant with distinct leaf bracts.', image_url: 'umbrella_plant.jpg' },
  { name: 'Verbena', description: 'Clusters of small, vibrant flowers; great for attracting butterflies.', image_url: 'verbena.jpg' },
  { name: 'Waxflower', description: 'Delicate star-shaped flowers and a lemony scent.', image_url: 'waxflower.jpg' },
  { name: 'Xeranthemum', description: 'Long lasting blooms known for their papery texture.', image_url: 'xeranthemum.jpg' },
  { name: 'Yucca', description: 'Striking appearance with sword-like leaves and large clusters of white flowers.', image_url: 'yucca.jpg' },
  { name: 'Zinnia', description: 'A garden favorite with bright, daisy-like head on a tall stem.', image_url: 'zinnia.jpg' },
]

flowers_data.each do |flower|
  Flower.find_or_create_by(name: flower[:name]) do |f|
    f.description = flower[:description]
    f.image_url = flower[:image_url] 
    end
end
```
画像はどちらでも大丈夫です！(image_url: 'waxflower.jpg)

<b>スクリプトを実行する
```ruby:bush
rails db:seed
```

:::note warn
注意
- 画像ファイルの管理: image_url は、app/assets ディレクトリ内に対応する画像ファイルが存在することを確認してください。
- データの重複防止: find_or_create_by メソッドを使用することで、同じ名前の花が複数回追加されることを防ぎます。
:::