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

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

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

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

Ruby on Rails

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

Q&A

解決済

2回答

2090閲覧

[Rails5]1対1のモデルについて

marokatsu

総合スコア38

Ruby

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

Ruby on Rails

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

0グッド

1クリップ

投稿2018/04/22 09:23

現在、簡単なSNSアプリを作ろうと思っているのですが、モデルの取り扱いについてわからなかったため質問いたします。

ユーザー1人はUserモデルとMyintroモデルを持っております.

Userモデルはdevise認証のGemで作ったものです。
1人のユーザーは1つの自分の詳細モデルを持つ、というイメージで考えており、
Userモデル1つにつき、Myintroモデルを1つ持っているものになります。

ここで、ユーザーを一人作った後、自分の詳細モデルを作る際
Myintroコントローラーのnewアクションを行うのですが
その中で、Userが持っているMyintroが一つであればeditページへ飛ばす、としたいのです。

質問

ユーザーがMyintroを一つ以上持っているならという条件を
if current_user.Myintro.length >=1
というようなコードで書けたらいいのですが、何かいい方法はありませんでしょうか?

Ruby

1class MyintrosController < ApplicationController 2 before_action :authenticate_user! 3 def index 4 5 end 6 def show 7 end 8 def new 9 # 現在のユーザーの紹介を作る 10 @length = current_user.myintro.length 11 # 現在のユーザーが詳細モデルをすでに持っていれば編集ページに遷移する 12 redirect_to edit_myintro_path(@myintro) 13 end 14 15 @myintro = current_user.build_myintro 16 end 17 18 def create 19 @myintro = current_user.build_myintro(myintro_params) 20 if @myintro.save 21 redirect_to edit_myintro_path(@myintro),notice:"プロフィール詳細を作成・保存しました" 22 else 23 redirect_to new_myintro_path,notice:"プロフィール詳細を作成できませんでした" 24 end 25 end 26 def edit 27 end 28 29 private 30 def myintro_params 31 params.require(:myintro).permit(:sex, :love_target) 32 end 33end 34

Ruby

1class Myintro < ApplicationRecord 2 belongs_to :user 3 4 #必須項目 5 validates :sex, presence: true 6 7end

Ruby

1class User < ApplicationRecord 2 # Include default devise modules. Others available are: 3 # :confirmable, :lockable, :timeoutable and :omniauthable 4 devise :database_authenticatable, :registerable, 5 :recoverable, :rememberable, :trackable, :validatable 6 has_one :myintro,dependent: :destroy 7end 8

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

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

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

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

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

guest

回答2

0

解決おめでとうございます。表記を正しく直しました。こちらが勉強になりました(笑)。

こんにちは。詳しくはないのですが、似た問題を解決しました。書籍を参考にしました。
devise のテーブル(Userモデルに該当)
ユーザ情報入力用のテーブル(Myintroモデルに該当)----user_id 列で、user.id を参照する。

書籍によって、devise 側のテーブル、変数を user としている場合と、ユーザの情報入力用のテーブル、変数を user としている場合があり、ややこしいです。プログラムの読み違えが起きそうです。

問題は、二つ。(以下)
問題は、切り分けると、ストレスが減ります(笑)。

(1)--ユーザの情報入力用のテーブルに、まだ、レコードがない場合---を、どのように if 文に書くか?

(2)--devise 側のテーブルから id を取得して、ここで、ユーザ情報入力用のテーブルに保存しないと、参照できない。
@ユーザ情報入力用インスタンス.new
@ユーザ情報入力用インスタンス.save
どちらも、ここで行うことになる。

書かれている if current_user.Myintro.length >=1 と同じだと思いますが、私が動作確認できた方法は以下です。

# ユーザ情報入力のテーブル---deviseモデル名_id 列--に、 # 今、ログインしている人の devise の id があるか確認する。 # where を使うので、配列で受け取り。 # @はいれつ[0]---最初の要素 @はいれつ = ユーザ情報入力モデル.where('deviseモデル名_id == ?', current_deviseモデル名.id) if @はいれつ[0] == nil then # まだ、ユーザ情報入力モデルのレコードがない。 # ここで、新規入力を行う準備。new,create の url 使わない。 @ひと = ユーザ情報入力.new # 参照される、devise のテーブルの id を代入。 @ひと.deviseモデル名_id = current_deviseモデル名.id # ここで、ユーザ情報入力モデルのテーブルに保存。 @ひと.save # 今、保存したレコードを where の検索。 @はいれつ = ユーザの情報入力モデル.where('deviseモデル名_id == ?', current_deviseモデル名.id) else # すでにユーザの情報入力テーブルにレコードがある。 # 過去にログインしたとき保存された。 end # 配列の最初の1個を代入 @ユーザの情報入力用インスタンス = @はいれつ[0]

コントローラ、if 文の中で、ユーザ情報入力テーブルに保存。つまり、ユーザ情報入力テーブルへの入力は、edit, update で行う。new, create ではない。
ややこしいです。理解するのに、かなり時間がかかりました。
今、読み返すと、自分で、忘れている部分があります。(あー)

投稿2018/04/23 05:11

編集2018/04/25 07:14
nekoyama7

総合スコア200

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

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

marokatsu

2018/04/23 14:59

nekoyama7さん 返信ありがとうございます! where文はまだ使ったことがなかったのですが、 newアクションで Myintroモデルを参照し、nilであれば作成する、という流れでしょうか。。。 MyintroコントローラーのnewアクションでdeviseのUserに紐付いたMyintroを作成し、 updateアクションで作ったMyintroを更新していく、ということだと理解しました。 ありがとうございました!
nekoyama7

2018/04/25 11:27

pekapekatailさんの書いていただいた、before_action を使う方法(まだ、じっくりコードを読んでませんが)で、new アクションを使うのが、流れが自然で良いと思います。参考にした本では、ユーザ情報入力のテーブル(Myintroモデル、テーブル)の1件のレコード作成を、index アクション(本来、複数のレコードを扱う)で行うという不自然なものでした。 save で保存した瞬間から、新規レコードではなくなるので、edit, update を使うというのも不自然。(new, create ではなく。)
marokatsu

2018/04/25 15:40

nekoyama7さん ありがとうございます。 myintroのnewアクションでidを引数で受け取っているわけではなかったため if User.find(params[:id]).myintro.all.length == 1 この:idでエラーが発生してしまい、色々試した結果下記の方法で何とか動きました。 if current_user.myintro != nil 1対1のモデルの扱いがまだはっきりとわかっていないため、また質問するかもしれません。 お時間がありましたらまたよろしくお願い致します。
nekoyama7

2018/04/26 01:38

お疲れ様です。プログラムで、大きなトラブルを減らせるコツとして、私が心がけているのは---- シンプルで、小さいサンプルを先に書く。---です。 いったん、devise のモデル、テーブルからはなれて、より、シンプルな物を考えた方が、急がば回れ---で、早いかも。
marokatsu

2018/04/26 14:57

ありがとうございます。 自分が作っているシステムをより簡単に。。。 わかりました。小さな機能から作って勉強します!
guest

0

ベストアンサー

ご質問拝見しました!
routes.rbのファイルも見せて頂けますでしょうか?

基本的には以下のようにnewアクションの前にbefore_actionで処理を行うのが良いのではないかと思います!

myintros_controller.rb

1before_action :myintro_counter, only: [:new] 2 3~~~ 4private 5def myintro_counter 6 if User.find(params[:id]).myintro.all.length == 1 7 redirect_to honyarara #UserがMyintroをちょうど一つ持っている時に飛ばしたい場所を指定 8 9 else 10 #そうでない場合の処理 11 end 12end

ちなみに、ご質問に「UserがMyintroを一つ以上持っているならという条件を」と書かれていましたが、has_oneを使ってアソシエーションされているので、もしご質問に書かれているように1:nの対応関係にするならhas_manyにする必要があります!

私も初心者ですが以上ご回答です!

投稿2018/04/22 19:36

pekapekatail

総合スコア32

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

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

marokatsu

2018/04/23 14:45

pekapekatailさん 返信ありがとうございます! コードも拝見しました。ひとつのユーザーに紐付いた自己紹介のモデルの数を取得する、ということですね。 気づきませんでした! Userは自分のプロフィールであるMyintroを一つだけ持つため1対1のモデルです。 ありがとうございました! routes.rb Rails.application.routes.draw do devise_for :users #get 'pages/index' root 'pages#index' resources :users, only: [:show] resources :myintros get 'myintros/:id/life' => 'myintros#life', as: 'manage_myintro_life' get 'myintros/:id/job' => 'myintros#job', as: 'manage_myintro_job' get 'myintros/:id/etc' => 'myintros#etc', as: 'manage_myintro_etc' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問