は、ユーザーが は市内
することができますに関連する国に割り当てられている限り、ユーザーに街を割り当てることができるようにしたいですあなたもしたいと思いませんか?
国を作成します。都市を作成し、それを国に割り当てます。旅行または訪問を作成し、その訪問または旅行を都市に割り当て、その旅行または訪問にユーザーを追加します。 Voila!あなたは必要な関係を持っています!おもう。
都市belongs_toの都市 訪問 ユーザーhas_manyの訪問 belongs_toの国 belongs_toの都市旅行、ユーザーhas_manyのは をトリップ両方の旅行や訪問は、市内に属しているので、あなたは、両側の関係を通じてhas_manyのを持つことができますしたがって、訪問と旅行のテーブルには市区町村とユーザーIDの両方が必要です あなたは必要な関係と必要な論理を持っています。
都市にユーザーを割り当てる方法がないため、都市にユーザーを直接参加させるなどの要件を守らないようにしないでください。実際には、さらに大きな頭痛を与えるだけでなく、多くの国の多くの都市を多くの訪問に連れて行きたいと思うかもしれません。その場合は、都市ではない旅行に訪問を割り当てる必要があります。
これはコーディングの問題ではなく、論理的な問題です。コンソールで、その後のコメント
class User < ApplicationRecord
has_many :trips
has_many :cities, through: :trips
end
class Trip < ApplicationRecord
belongs_to :user
belongs_to :city
end
class City < ApplicationRecord
has_many :trips
has_many :users, through: :trips
end
に対応して
UPDATE
Loading development environment (Rails 5.1.4)
2.4.0 :001 > u = User.create(name: "Fred")
(0.0ms) begin transaction
SQL (0.3ms) INSERT INTO "users" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "Fred"], ["created_at", "2017-09-17 14:24:30.720005"], ["updated_at", "2017-09-17 14:24:30.720005"]]
(16.3ms) commit transaction
=> #<User id: 1, name: "Fred", created_at: "2017-09-17 14:24:30", updated_at: "2017-09-17 14:24:30">
2.4.0 :004 > c = City.create(name: "Leeds")
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "cities" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "Leeds"], ["created_at", "2017-09-17 14:26:19.293166"], ["updated_at", "2017-09-17 14:26:19.293166"]]
(33.9ms) commit transaction
=> #<City id: 1, name: "Leeds", created_at: "2017-09-17 14:26:19", updated_at: "2017-09-17 14:26:19">
2.4.0 :005 > t = Trip.create(name: "T1", user: u, city: c)
(0.2ms) begin transaction
SQL (0.5ms) INSERT INTO "trips" ("user_id", "city_id", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["user_id", 1], ["city_id", 1], ["name", "T1"], ["created_at", "2017-09-17 14:28:44.656390"], ["updated_at", "2017-09-17 14:28:44.656390"]]
(26.0ms) commit transaction
=> #<Trip id: 1, user_id: 1, city_id: 1, name: "T1", created_at: "2017-09-17 14:28:44", updated_at: "2017-09-17 14:28:44">
2.4.0 :006 > t.user.name#
=> "Fred"
2.4.0 :007 > t.city.name
=> "Leeds"
2.4.0 :008 > t.name
=> "T1"
だから、作品を通してどのように通常のhas_manyのだが、私はどのように更新しますので、あなたが旅行モデル上にhas_many都市をしたいですまもなく働くだろう
OK、旅行には多くの都市と都市がありますhas_many trips has_manyはあなたの関係の両側にありますおそらくtrip_city_xrefと呼ばれる新しい相互参照テーブルが必要になります。これはcity_idとtrip_idの複合主キーを持っています
これは私が嫌うhas_and_belongs_to_many関係です。私の意見では、has_and_belongs_to_manyは、Railsが間違っていた唯一のものに関するものでした。それは短絡です。他の人はそれに同意しませんが、これは私がショートカットを持たない言語でこれを設定する方法です。私はそれがより明確であいまいではないと思う。だから私はそうだから、あなたが今、あなたのユーザーに何をしますかhas_and_belongs_to_manyアソシエーションhere をよく読んで行く気軽にちょうど私の意見です。この
class Trip < ApplicationRecord
belongs_to :user
belongs_to: :city_trip_xref and
has_many :cities, through: :city_trip_xref
end
class City < ApplicationRecord
has_many :trips, through: :city_trip_xref
has_many :users, through: :trips
end
class CityTripXref < ApplicationRecord
belongs_to :trip
belongs_to :city
end
のようなものを設定するのでしょうか?繰り返しますが、私は、だからあなたのユーザ・モデルは、ユーザーがあなたが関係を平らにしてマッピングすることができます旅行で訪問しているすべての都市を取得するには、この
class User < ApplicationRecord
has_many :trips
has_many :city_trip_xrefs, through: :trips
def cities
trips.map(&:city_trip_xrefs).flatten.map(&:city)
end
end
ようになり、まもなく
UPDATE User.cities を更新します(:city_trip_xrefs &).flatten.map(&:市)のu = User.first u.trips.mapので よう
ですから、上記のように使用して都市を取得するには、ユーザーのクラスにメソッドを作ることができます上記のユーザーモデルに示されています。とにかく、都市をユーザーに割り当てることについては、実際には直接行う必要はありません。あなたは旅行を設定し、その旅行にユーザーと都市を追加し、あなたの要件が多少異なる場合を除き、実際の例で必要と思われるすべての機能を持っています。
上記の作成されたレコードコンソールプラスワン既存の都市のための都市への多くの旅行に多く参加し、あなたをトリップするcity_trip_xrefテーブル内のレコードに今できること
まずコンソールで外部参照を作成
ctx = CityTripXref.new
=> #<CityTripXref id: nil, city_id: nil, trip_id: nil, created_at: nil, updated_at: nil>
2.4.0 :008 > ctx.city = City.first
=> #<City id: 1, name: "Leeds", created_at: "2017-09-17 14:26:19", updated_at: "2017-09-17 14:26:19">
2.4.0 :009 > ctx.trip = Trip.first
=> #<Trip id: 1, user_id: 1, city_id: 1, name: "T1", created_at: "2017-09-17 14:28:44", updated_at: "2017-09-17 14:28:44">
2.4.0 :010 > ctx.save
次のget最初のユーザーの最初の旅行の最初の都市の名前
2.4.0 :028 > u = User.first
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<User id: 1, name: "Fred", created_at: "2017-09-17 14:24:30", updated_at: "2017-09-17 14:24:30">
2.4.0 :029 > u.cities.first.name
Trip Load (0.1ms) SELECT "trips".* FROM "trips" WHERE "trips"."user_id" = ? [["user_id", 1]]
CityTripXref Load (0.1ms) SELECT "city_trip_xrefs".* FROM "city_trip_xrefs" WHERE "city_trip_xrefs"."trip_id" = ? [["trip_id", 1]]
City Load (0.1ms) SELECT "cities".* FROM "cities" WHERE "cities"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> "Leeds"
2.4.0 :030 >
希望があります。
'countries_users'と' cities_users'という2つの標準ジョインテーブルを作成し、後者に**モデル検証**を書いて、その都市がユーザに割り当てられていることを表明できますか? –
サイドノート:おそらく、ユーザーがある国から**割り当てられていない**を防止するために、削除前または削除後のロジックを必要とするかもしれませんが、まだ都市に割り当てられたままです。 (つまり、そのような削除を禁止するか、トランザクションの一部として他の関連付けを削除するかのいずれかです。) –
ユーザーはhas_many都市として都市を割り当てることはできません。ユーザは、都市をユーザに割り当てることができるように、所属する必要があります。あなたが本当に望むのは、ユーザーに訪問を割り当て、訪問に都市を割り当てることです。あなたの質問を理にかなっているものに更新し、私がさらに助けることができるかもしれません。あなたの問題を引き起こしているシンプル化をスクラップして、あなたの要求を破るようなことをすることができると思うようにしてください。 – jamesc