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

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

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

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

Q&A

解決済

2回答

514閲覧

Railsでモデルを生成する際に、特定のカラムの中の最大値+1で設定する方法

etsuhisa

総合スコア416

Ruby on Rails

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

0グッド

0クリップ

投稿2020/05/16 07:45

前提・実現したいこと

Railsでモデルを生成する際に、特定のカラムの中の最大値+1で設定する方法を教えてください。

Ruby

1Hoge.create(ord: xxx, name: 'D')

上記xxxの個所は以下のSQLで設定できる値にしたいです。

SQL

1insert into t select coalesce(max(ord)+1,1),'D' from t where name='D';

テーブルtのデータは以下のようになっており、上記SQLにより「1,'D'」の行が増えるようになります。

SQL

1select * from t; 2+------+------+ 3| ord | name | 4+------+------+ 5| 1 | A | 6| 1 | B | 7| 1 | C | 8| 2 | A | 9| 3 | A | 10| 2 | B | 11+------+------+

発生している問題・エラーメッセージ

なし

該当のソースコード

最初に記載したとおりです。

試したこと

create内でwhereとmaximumで取得した場合、同時更新に対応できないと思い、他の実現方法を探しています。

補足情報(FW/ツールのバージョンなど)

特にありません。

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

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

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

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

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

guest

回答2

0

ベストアンサー

Rails的な記述で書くのはできないような予感。(識者を待つ)

案1) 生SQLを書いてしまう。ord以外の項目も生で書くのはしんどいかもですが、その場合は とりあえず 生SQLでordを確保して、それからupdateする

案2) ordをautoinclimentalにしてしまう。

追記
案2はだめですね。 同じ内容の時に+1なんですね

追記2
もしかしたら案2でもいけますね。
ordって同じ内容の時の order のためのもので、「Aの2番めのものを取り出す」ためのものではない  ですよね。
でしたら
+------+------+
| ord | name |
+------+------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | A |
| 5 | A |
| 6 | B |
+------+------+
となってもOKでは?

投稿2020/05/16 11:52

編集2020/05/17 00:35
winterboum

総合スコア23567

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

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

etsuhisa

2020/05/16 12:56

なるほど!ordで管理しているわけではないので、別々に処理するのはよいかもしれませんね。 最悪がっつり排他するしかないかと思っていましたので、よいアイデアをいただきました。
etsuhisa

2020/05/17 00:57

ご回答ありがとうございます。 ただ、name=A&ord=2で情報を取得するような「Aの2番めのものを取り出す」という要件があり、ordが必要となっています。
winterboum

2020/05/17 01:09

なるほど。 ではしつこく W where(name: "A").order(:ord).offset(1).first いえ、案1で行けるならOKです。お遊びでのしつこく ですのでその気で読んでください Rails のmigration で AutoInclimentって指定できるのかな、、という新しい問題も出てきてしまいますからね
etsuhisa

2020/05/17 11:36

いろいろありがとうございました。 当初の1SQLでの実現はあきらめました。 最終的には、通常通りHogeのbefore_saveでordを最大+1で設定するようにし、データベース側で[:name, :ord]をunique:trueで設定することで、重複したordが設定されるのを防ぐようにしました。 self.ord = Hoge.where(name: "A").maximum(:ord).to_i + 1 add_index :hoges, [:name, :ord], unique:true もし、衝突をエラーとしない要件が出た場合には、例外を捕捉してリトライするような仕組みを考えます。
guest

0

ruby

1max = Hoge.maximum(:ord) + 1 2Hoge.create(ord: max, name: 'D')

投稿2020/05/16 11:26

NCC1701

総合スコア1680

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

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

winterboum

2020/05/16 11:47

これですと 「create内でwhereとmaximumで取得した場合、同時更新に対応できないと思い」 の問題は解決していないのでは
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問