yosaku_ibs
@yosaku_ibs

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【Rails】createの際、enumのカラムをシンボルで定義できるのはなぜ??

Q&A

Closed

質問したいこと

enumに関する質問です。
どうしてcreateする際にシンボルでenumを定義することができるのでしょうか?
(下記ソースコードですと、sales_statusというカラムの内容を定義する際に、sales_status: :now_on_saleと定義しています。)

本当なら" "で定義するのが一般的だと思うのですが...。

ソースコード

app/models/book.rb

classBook<ApplicationRecord
  enumsales_status:{
  reservation:0,#予約受付
  now_on_sale:1,#発売中 
  end_of_print:2,#販売終了
  }
end

irb(main):001:0> Book.create(
irb(main):002:1* name:"enumBook1",
irb(main):003:1* sales_status::now_on_sale,
irb(main):004:1* publisher:Publisher.find(1),
irb(main):005:1* price:100
irb(main):006:1> )
=>#<Bookid:5,name:"enumBook1",略,sales_status:"now_on_sale">

自分で試したこと

ネットで検索しましたが、シンボルでの定義についての書かれた情報に
出会えませんでした。

以上、お手数ではございますが
もしご存知の方がいらっしゃいましたら
ご教示の程よろしくお願い申し上げます。

0

1Answer

明確に書かれていませんが、 enum のキーと値を対応づけるマッピングは、キーが文字列でもシンボルでも同じ値を返すように実装されています。

以下の例では Conversation.statuses がマッピングです。これは ActiveRecord::HashWithIndifferentAccess インスタンスで、 Hash のサブクラスですが、キーにシンボルが渡されるとまず文字列化してから扱うようになっています。

class Conversation < ActiveRecord::Base
  enum :status, [ :active, :archived ]
end

Conversation.statuses[:active]    # => 0
Conversation.statuses["archived"] # => 1

create に渡した enum はこのマッピングを使って値に変換されるので文字列でもシンボルでも動きます。

0Like

Comments

  1. @yosaku_ibs

    Questioner

    @uasi様

    おはようございます。
    いつも大変お世話になっております。
    ご回答くださり誠にありがとうございます。

    >enum のキーと値を対応づけるマッピングは、キーが文字列でもシンボルでも同じ値を返すように実装されています。

    uasi様のこの一文をきっかけに私自身でも再度検索しますと、
    リファレンスのシンボルの実装についてのページで同様の説明がされておりました。

    >Rubyの内部実装では、メソッド名や変数名、定数名、クラス名など の`名前'を整数で管理しています。これは名前を直接文字列として処理するよりも 速度面で有利だからです。そしてその整数をRubyのコード上で表現したものがシンボルです。
    シンボルは、ソース上では文字列のように見え、内部では整数として扱われる、両者を仲立ちするような存在です。
    名前を管理するという役割上、シンボルと文字列は一対一に対応します。 また、文字列と違い、immutable (変更不可)であり、同値ならば必ず同一です。
    https://docs.ruby-lang.org/ja/2.3.0/class/Symbol.html

    これはつまり、「前提条件として、シンボルと文字列は一対一になるように実装されており、enumでもシンボルと文字列を一対一で扱える。」
    という認識で差し支えございませんでしょうか?

    以上、お手数ではございますが
    ご教示お願い致します。
  2. シンボルと文字列は一対一で対応しますが、別物です。普通の Hash のキーとしても区別されます。

    ```
    p "key" == :key # => false

    h = {}
    h["key"] = "str"
    h[:key] = "sym"

    puts h["key"] # => str
    puts h[:key] # => sym
    ```

    この区別が煩わしい場合があるため、 Rails では、文字列を期待する箇所にシンボルが渡されたら文字列に変換してから扱う(その逆も同様)という処理が組み込まれている場合が多いです。 enum はその一例です。

    Rails でもシンボルのみ・文字列不可、またはその逆なコードがあるので、混ぜて扱わないようにしてください。
  3. @yosaku_ibs

    Questioner

    uasi様

    いつも大変お世話になっております。

    >Rails では、文字列を期待する箇所にシンボルが渡されたら文字列に変換してから扱う(その逆も同様)という処理が組み込まれている場合が多いです。 enum はその一例です。
    Rails でもシンボルのみ・文字列不可、またはその逆なコードがあるので、混ぜて扱わないようにしてください。

    シンボルの話は別物扱いになるのですね。。。
    以後分けて考えるように致します。

    enumには、「キーをシンボルで受け取るとそれを文字列化して扱う」という機能が実装されているとわかりました。

    いつも丁寧に解説くださりありがとうございます。

    以上、御礼申し上げます。

Your answer might help someone💌