質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

9840閲覧

Ruby frozen_string_literal について

E-T

総合スコア14

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

5クリップ

投稿2017/05/02 01:03

前置き

突然の投稿失礼します。
Ruby開発初心者なのですが、
知識と経験不足で開発の定石や基礎部分がうまく理解できておらず質問を投稿させていただきます。

先月Rubyで開発を行い、ソースコードのレビューで指摘を頂いた時に色々と疑問に思ったことがあり、
その中で一点どうしても理解できないところがありましたのでご助言をお願いします。

指摘を受けた部分は、rubocopで構文チェックを行いソースコードを訂正した箇所にあります。
rubocopを実行させた際に

Missing frozen string literal comment.

という上記の警告が発生したため、調査して下記のコメントを付与することで問題を解決していました。

# frozen_string_literal: true

この対応を行った箇所に対して
「その記述は必要ですか?」
というご指摘をレビューの際にいただき、今一度必要性を調査したところ謎が深まりわからなくなりました。
どうかご教示をお願いします。

###環境
Ruby : 2.3.1
Rails : 5.0.2
構文チェック : rubocop

###疑問点

  • 通常の開発を行う際は、rubocopのfrozen_string_literalに関してどう対応しているのか。

(.rubocop.ymlに設定するのか、警告の出たソースコードを修正する等)
※その対応の理由も教えていただきたいです。

調査したところ、文字列リテラルの扱いに関する記述・対応ということ、
rubocopが標準でfrozen_string_literalを検査していること、
またrubyのversionが3.0になる際に大きく関わるということは多少理解しました。

↓参考にさせて頂いた資料
http://d.hatena.ne.jp/ku-ma-me/20151004/p1
http://www.task-notes.com/entry/20160831/1472572735

見当外れなことをお聞きしているかもしれませんが、是非ご教示お願いします。
よろしくお願いします。
必要な情報などがございましたらご提示致しますのでその際はお手数ですがお声掛けしていただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

frozen_string_literalについて

rubyにおいて、文字列(Stringオブジェクト)は**mutable(破壊的に変更可能)**なデータです。
ruby reference: class String
例えば、以下のコードは変数str/str2に一度しか代入していないにもかかわらず、参照のタイミングによって内容が異なっています。

ruby

1str = 'test' 2str2 = str 3 4print str, str2 # => testtest 5str.upcase! 6print str, str2 # => TESTTEST

一般に、オブジェクトの破壊的変更はコードの可読性を下げ、バグを誘発する傾向にあります。あるオブジェクトをコードのどこかで破壊的に変更すると、そのオブジェクトを参照している箇所全体に影響を与えるからです(上記コードのstr/str2の関係)。
そこで、従来のrubyでは文字列の破壊的変更を禁止するため、freezeメソッドを呼ぶといった対策を取ってきました。

str = 'test' str.freeze str.upcase! # => RuntimeError: can't modify frozen String

しかし、文字列というごく一般的なデータを取り扱うために都度freezeを付けるのは面倒臭い + freezeが必要/不要を考えず、文字列に片っ端からfreezeを付ける実装が跋扈してきたということから、「そもそもデフォルトで文字列をimmutable(破壊的な変更不可)にしてしまおう」という方針が、ruby3.0以降で決定しています。
[Ruby] Ruby 3.0 の特大の非互換について

そして、将来ruby3.0がリリースされた時にruby2.x系からスムーズに以降できるよう、「デフォルトでStringをimmutableにする」という機能をruby2.x系で限定的に取り込んだのがfrozen_string_literalというマジックコメントです。

frozen_string_literalの対応

私は原則、rubocopの指針に従ってfronze_string_literal: trueをソースコード内に追加するようにしています。その方が、将来バージョンアップ時の手間が減る(ruby3.0では、frozen_string_literalは単なるコメントとして扱われる予定)ことと、デフォルトでimmutableにした方が予期せぬバグを抱えにくいからです。
ただ、config系のファイル、テストコード、migrationファイルはrubocopによるチェックの対象外としています。
migrationファイルはほぼrailsで自動生成したものをそのまま使う、configはそもそも設定を書き下すだけでデータ操作はしない、テストコードは実際の動作に関わらない、といった理由から、そこまで厳密なコーディングをしなくても良いだろう、という判断です。

投稿2017/05/02 02:47

編集2017/05/02 02:53
philomagi

総合スコア267

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

E-T

2017/05/02 03:04

ありがとうございます! 大変わかりやすく解説していただき、かなり理解を深めることができました。 rubocopの設定も非常に参考になりました。 解説して頂いた情報と、記事を読んだ所感ですが、私も引き続きfrozen_string_literal: trueをソースコードに追記する対応を維持していこうと思います。 ただ、今回は最初に「rubocopの対象ファイルはどうするか、規約はどの程度のものを設定するか」という部分をしっかり策定できていなかったため、今後はその部分の流れも頭に入れてから構文チェックを走らせていこうと思います。 この度は本当にありがとうございました。 重ねて御礼申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問