ユーザー(出品者)がサービス(商品)を出品し、別のユーザー(購入者)がそれを購入できるというケースを想定した場合、以下の考え方で正しいでしょうか?誤りがあればご指摘頂けますと幸甚です。
前提
・ユーザー(出品者)とサービス (商品): 1対多の関連付け
・サービス(商品)とユーザー(購入者) : 多対多の関連付け *1つのサービス(商品)に複数のユーザー(購入者)が購入できる前提。
・ユーザーは出品者にも購入者にもなれる : 出品者と購入者は同じmodel
モデル(正しいでしょうか?)
・上記前提を元にすると、必要となるmodel
はUser
とProduct
とEntry
(productとそれを買うuser(購入者))を多対多の関連付けで使用する中間テーブル)の3つ
・すなわち、以下のイメージ
user
(1)<-> (多)product
(1) <-> (多)entry
(多) <->(1) user
各モデルのテーブル(migration file) *単純化してます
User
#User
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :email, null: false # メールアドレス
t.string :family_name # 姓
t.string :given_name # 名
t.string :address # 住所
t.text :user_profile # プロフィール
t.string :hashed_password # パスワード
t.timestamps
end
end
end
#Product
class CreateProducts < ActiveRecord::Migration[5.0]
def change
create_table :products do |t|
t.references :user #外部キー
t.integer :price #価格
t.string :title #タイトル
t.datetime :posted_at #商品投稿日
t.binary :data #写真
t.timestamps null: false
end
end
end
#Entry
class CreateEntries < ActiveRecord::Migration[5.0]
def change
create_table :entries do |t|
t.references :product, null: false
t.references :user, null: false
t.timestamps
end
end
end
各モデルの書き方
#Userモデル
class User < ApplicationRecord
has_many :products, dependent: :destroy
has_many :applied_products, through: :entries, dependent: :destroy, source: :product
has_many :entries, dependent: :destroy
end
#Productモデル
class Product < ApplicationRecord
belongs_to :user
has_many :entries, dependent: :destroy
has_many :applicants, through: :entries, source: :user
end
#Entryモデル
class Entry < ApplicationRecord
belongs_to :applied_products, class_name: "Product", foreign_key: "product_id"
belongs_to :applicants, class_name: "User", foreign_key: "user_id"
end
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+2
同じ種類の「商品」が複数あった場合、それらの商品の集まりを"1つの物"としてとらえる考え方と、個々の商品をそれぞれ"1つの物"としてとらえる考え方がありますが、個々の商品を"1つの物"として扱う方が考えやすいです。
というのは、複数の商品をひとまとめで考えると、購入者ごとの購入数の合計が商品数を超えないように常に状態を管理する必要があるので、複雑になるからです。
個々の品物をそれぞれ"1つの物"とするなら、
・ユーザー(出品者)と商品 : 1対多の関連付け (ある品物を出品するのは一人だけ、但し一人が複数の品物を出品できる)
・商品とユーザー(購入者) : 多対1の関連付け (ある品物を購入するのは一人だけ、但し一人が複数の品物を購入できる)
になります。
ある人は出品者にも購入者にもなれる。
しかし売買に関する役割(role)が異なりますから、出品者と購入者のモデルは別々にしたほうが素直だと思います。
そうすれば1つの商品に関した関係が、下記のように単純なものになるからです。
(購入者が居ない状態では、buyerが存在しない関係になります)
seller(出品者) - item(個別の商品) - buyer(購入者)
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
checkベストアンサー
0
・上記前提を元にすると、必要となるmodelはUserとProductとEntry(productとそれを買うuser(購入者))を多対多の関連付けで使用する中間テーブル)の3つ
やりたい事に対して、この構成の作り方は、正しいと思います。
1番シンプルですね。
ただし、テーブルを見ると、Entryのカラムが足りないですね。
このままだと、ユーザと商品の紐付けはわかりますが、ユーザの立場(出品or購入)がわかりません。
Entryテーブルに、出品or購入がわかるようなflag用のカラムを増やしてあげると、やりたい事が出来る構成になるはずです。
本題のmodelの紐付け部分ですが、
・すなわち、以下のイメージ
user (1)<-> (多)product(1) <-> (多)entry(多) <->(1) user
ここも少し違いますね。
書き方を合わせて書くと、
product(1) <-> (多)entry(多) <->(1) user
だけですね。
では、これをどうコード化するかと言うと、
# app/models/user.rb
class User < ActiveRecord::Base
has_many :entries
has_many :products, through: :entries
end
# app/models/entry.rb
class Entry < ActiveRecord::Base
belongs_to :user
belongs_to :product
end
# app/models/product.rb
class Product < ActiveRecord::Base
has_many :entries
has_many :users, through: :entries
end
こうですね。
以下のサイトがほとんど同じことをやっているので、参考に読んでみてください。
Rails4で多対多のリレーションをモデルに実装する
あと、余談ですが、dependent: :destroy
は今回のケースでは使わない方が良いと思いますよ。
ユーザを削除したりしても、関連する商品を消されては困るはずなので。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.10%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
IPU
2017/01/18 12:14
modelの紐付けの前に、どんなテーブルで作る予定かを書かないと伝わりづらいと思います。
innjera
2017/01/18 12:34
情報かけており申し訳ありません。今しがた編集致しました。宜しくお願い致します。