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

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

ただいまの
回答率

90.51%

  • Ruby

    7651questions

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

  • Ruby on Rails

    7259questions

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

データの型を見て、自動でコンポーネントを出力したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 378

nae_stage

score 61

やりたいこと
オブジェクトのデータの型を見て、
「integer」ならスピンボタンがついたテキストボックスを
「datetime」ならカレンダーピッカーを
「string」ならただのテキストボックスを
自動で表示できるような仕組みを作ろうとしています。

やったこと・問題点
このサイトなどを見て、「datetime」や「integer」という型が存在することを確認し、
以下のような部分テンプレートを作成しました。
この部分テンプレートを各viewから呼び出して使用します。(「model」にはビューから渡ってきたデータが入ります)

(pertial.html.erb)
<% if model.class === "Integer" %>
    スピンボタンがついたテキストボックスを表示
<% elsif model.class === "Datetime" %>
    カレンダーピッカーを表示 
<% elsif model.class === "String" %>
    ただのテキストボックスを表示  
<% end %>


そして、以下のコマンドを実行し、画面を作成し、上記部分テンプレートを呼び出しました。

rails g scaffold todo name:string date:datetime number:integer price:decimal
<%= render 'pertial', model: @todo.date %>


ところが、実行してもカレンダーピッカーが表示されませんでした。
同じように、スピンボタンがついたテキストボックスも表示されませんでしたが、
ただのテキストボックスは表示されました。

model.classの中身を見てみると、以下のように型が変化していました。
datetime ⇒ ActiveSupport::TimeWithZone
integer ⇒ Fixnum
string ⇒ 変化無し

そこで、部分テンプレートを下記のように変更しました。

(pertial.html.erb)
<% if model.class === "Fixnum" %>
    スピンボタンがついたテキストボックスを表示
<% elsif model.class === "ActiveSupport::TimeWithZone" %>
    カレンダーピッカーを表示
<% elsif model.class === "String" %>
    ただのテキストボックスを表示   
<% end %>


しかし結果は変わらず、ただのテキストボックスしか表示できませんでした。

(1)なぜ型が変わるのか
(2)なぜ型が合ってるはずなのに、分岐を通り過ぎてしまうのか
(3)なぜStringだけうまくいくのか
(4)どうすればやりたいことが実現できるのか
お分かりの方、ご教授いただけませんでしょうか。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

色々と間違っているので何から突っ込んだらいいか…
多分javascriptあたりからいらしたんでしょうrubyは別世界ですからね。
とりあえず質問に答える前に以下の前提を考慮してください。

1「datetime」や「integer」という型はDataBaseにおける型です。
参考サイトはあくまでDataBaseを作る際のデータの形式(型)を指定してるだけで
Rubyとはあまり関係ありません
※ちなみに型というのは数学的に言うと演算について閉じている(同じ型同士は足したり引いたりできる)と言う意味です。

Rubyに型といえば数字と文字あとはArrayとHashぐらいでしょうか?
ruby においてはミミズだってオケラだって、Integerだって(nilさえも)
みんなみんなClassです。methodが使えます。Classと型とは異なることをご理解ください。

2 部分テンプレートは通常このような用途には使いません
こういった場合Helper Methodを構築します。

3 rubyは===をあまり使いません、型を意識しないのが売りなので通常
==で事足ります。 ex 1=="1"  => true

4 ruby で Class はイニシャルが大文字で表されます。
'String'とかで表されるわけではありません。
なので、"文字列".class==String => ture となります。

5 かえって混乱を招きますが===だとこういう面白いことが起こります。
"文字列"===String => false
String==="文字列" => true

これでnae_stage様の1−3の質問に答えられたと思います。

4に関しましてはcase when を使って(実はこの評価で===が使われます。)
helpers/application_helper.rbに

def hoge_helper(model)
 case model
  when Fixnum
  スピンボタンがついたテキストボックスを表示
  when ActiveSupport::TimeWithZone
 カレンダーピッカーを表示
  when String
 ただのテキストボックスを表示 
 end
end  


と追記してください
そしてviewで

<%= hoge_helper(model) %>


と使うのがいいと思います。
私はこれをいつ使うのか見当がつきませんが…。

わからないことがあったらコメントください

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/05 13:26

    丁寧なご回答ありがとうございます!一からしっかり勉強する必要性を感じました・・・
    いただいた回答について、さらに質問させていただけますでしょうか?

    (1)回答の1について
    Railsでは「datetime」型は無い・「datetime」クラスは無いため、
    DBから「datetime」型として取得したデータは、
    Railsによって自動的に、「datetime」を扱うのに適している「ActiveSupport::TimeWithZone」クラスのオブジェクトにされる
    という認識で合っていますでしょうか?

    (2)回答の5と、記載いただいたhelpers/application_helper.rbのコードについて
    "文字列".class===String => false
    であるならば、
    case whenで評価すると、model.classの値がどの条件に当てはまらず、素通りしてしまうと思うのですが、
    いかがでしょうか?
    試しにいただいたcase whenで評価したコードを動かすと、全ての条件を素通りしてしまいました。
    さらに、ifと==での評価に書き換えると、model.classの値がFixnumの場合、when Fixnumの分岐の中に入っていきました。
    いただいた回答に対する私の解釈が間違っておりましたら、ご指摘いただけませんでしょうか?

    (3)これをいつ使うのかについて
    ASP.NET MVCで開発していた時、
    データの型や、指定したDataTypeの値によって、
    テンプレートビューを自動で選択し、コンポーネントを出し分けることができる仕組みがあったため
    (参考URL:http://www.buildinsider.net/web/bookaspmvc5/040402)
    同じことができないかどうか、考えていた次第です。

    以上、よろしくお願いします。

    キャンセル

  • 2017/04/05 14:45

    (1)あっています。しかしこれはRailsのversionによって変わりかねないので注意が必要です。
    (2)ミスです回答を訂正しておきました。
    (3)Railsはデータの変更をModelを中心にやります。DataBaseのデータタイプが付与されて構造もあらかじめ決まっているので動的に変わることは想定されていません。
    例えば、データ構造が定まっていないJsonファイルやXmlファイル(はさすがにないか)だと
    こういった必要が出てくると思いますが、それは便利なライブラリがあったと思います。思い出したら追記します。

    キャンセル

  • 2017/04/05 15:25

    ありがとうございます。大変勉強になりました。
    「===」演算子・case式は、色々作ってみて慣れていこうと思います。

    キャンセル

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

  • ただいまの回答率 90.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    Rubyでのプログラムの問題

    前提 Ruby 書籍「プログラマ脳を鍛える数学パズル」より問題箇所を抜粋。 プログミング歴がまだ半年と短く、ど素人当然の質問をしてしまいますが、何卒よろしくお願いします。

  • 解決済

    if文のorで分岐した際に表示されるWarningについて

    発生している問題・エラーメッセージ if文において下記のように条件分岐した際、warningメッセージで出てしまいます。 試した事に記述した方法では冗長だと思うので正解では無い

  • 解決済

    rails : form_forメソッドのeditでTimeクラスのオブジェクトがセットされない

    Rails 5.0.0.1にて開発しています。デザインにはbootstrapを利用しています。 form_forにてeditアクション用のフォームを表示すると、datetim

  • 解決済

    【Ruby】エラーの原因を探せない...

    前提・実現したいこと 前回に引き続き、自分で書いたコードのエラーが探せずにいるので見て頂きたいです。 ※エラーを探すコツってあったりするのでしょうか... 発生している問

  • 解決済

    テキストから読み込んだ日付・時間の比較

    いつもお世話になります。 現在、cronを使用して一定時間Aという処理がない場合にBという処理を行いたいと思っております。 具体的には処理Aが行われるたびに、そのときの日付

  • 解決済

    rubyで一ヶ月間の日付と曜日を出力したい。

    ruby初心者です。 やりたいことの理想形を書きます。 例えば… ステップ1 make_day.rbというファイルを作っTerminalで実行すると 「西暦を入力して下さい

  • 解決済

    ネストの深いhashのパスを再帰的に取得したい

    前提・実現したいこと ネストの深いhashのパスを再帰的に取得したい 以下のようなネストのあるHashのパスをネストがなくなるまで再帰的に取得したいと考えています s

  • 解決済

    rails validateについて

     前提・実現したいこと 投稿の際に昨日以前に日付設定した場合に投稿できないように機能を実装したい。 railsで指定した日付以降に開ける投稿アプリを作っています。 上記の機能を

同じタグがついた質問を見る

  • Ruby

    7651questions

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

  • Ruby on Rails

    7259questions

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