Hier sind meine Models:Einmaligkeit Validierung auf has_many Verein Aufzeichnungen über accepts_nested_attributes_for
class User < ApplicationRecord
has_many :cities_users, inverse_of: :user
has_many :cities, through: :cities_users
accepts_nested_attributes_for :cities_users
end
class CitiesUser < ApplicationRecord
belongs_to :user
belongs_to :city
validates :user_id, uniqueness: { scope: :city_id, message: "already specified that they have lived in this city"}
end
class City < ApplicationRecord
has_many :cities_users
has_many :users, through: :cities_users
end
Während eine neue user
Datensatz zu erstellen: Der Benutzer kann dynamisch Städte hinzufügen, die sie in (über die nested_form_fields gem) gelebt haben. Dies erstellt schließlich Datensätze in der Join-Tabelle cities_users
.
Nach einem Klick auf die 'eine Stadt hinzufügen Sie in gelebt haben' Button:
Benutzer dann geht und klickt auf die Schaltfläche wieder andere Stadt hinzuzufügen:
In dieser Situation oben möchte ich einen Validierungsfehler auslösen, wenn der Benutzer auf die Schaltfläche Create User
klickt. Beim Erstellen eines neuen Benutzerdatensatzes: Ein Benutzer sollte NICHT angeben, dass er mehr als einmal in derselben Stadt gelebt hat.
So oben: ohne Validierung: zweicities_users
Aufzeichnungen würden mit der gleichen user_id
und city_id
erstellt werden. Das ist nicht gut, also möchte ich das Formular erneut rendern, die zwei verschuldeten cities_users
verschachtelten Felder markieren und eine Fehlermeldung wie "Sie können nicht angeben, dass der Benutzer mehr als einmal in derselben Stadt gelebt hat" ausgeben lassen.
Dies erfordert eindeutig eine Validierung entweder auf dem user
Modell oder dem cities_user
Modell. Ich weiß nicht, wohin die Validierung gehen soll, und ich weiß nicht, wie ich die Validierung so programmieren soll, dass sie diesen Fehler erkennt. Die aktuelle uniqueness
Validierung, die ich auf dem CitiesUser
Modell habe, fängt diese Situation nicht ein.
zusätzliche Setup-Informationen nur für den Fall jemand will das Szenario neu
Das war, wie ich die nested_fields innerhalb des Benutzers einrichten _form.html.erb
:
<%= f.nested_fields_for :cities_users do |ff| %>
<div>
<%= ff.label :city_id %>
<%= ff.collection_select(:city_id, City.all, :id, :name) %>
</div>
<% end %>
<br>
<div><%= f.add_nested_fields_link :cities_users, "Add a City You have lived in" %></div>
Die users_controller#create
Aktion ist Standard, erzeugt aus der scaffold
Befehl. Ich habe den starken params hinzufügen, um für die verschachtelten Attribute zu ermöglichen:
def user_params
params.require(:user).permit(:name, cities_users_attributes: [:id, :city_id, :user_id])
end
Dank für Ihre Antwort danken. Diese Antwort ist nah, aber wie es nicht funktioniert. 'self.users_cities' gibt ein Collection-Proxy-Objekt zurück. Was ich getan habe, ist, dass ich die 'no_duplicate_cities' private Methode erstellt habe, einen Haltepunkt dort,' self.users_cities' genannt, um zu sehen, was es mir zurückgeben würde. Hier ein Beispiel: '#, # , # ]> ' –
Neil
vielleicht muss ich irgendwie die Items durchlaufen Suchen Sie in collection_proxy, ob bereits ein Element mit dieser 'city_id' in der Liste vorhanden ist, und lehnen Sie es gegebenenfalls ab? – Neil
Ich hatte Hoffnungen, dass dies das tun würde, aber es ist nicht. irgendwelche Vorschläge? 'self.users_cities = self.users_cities.uniq {| user_city | user_city.city_id} ' – Neil