Как мне отказаться, если существует? для не вложенных атрибутов? - PullRequest
2 голосов
/ 01 апреля 2010

В настоящее время мой контроллер позволяет пользователю отправлять несколько «ссылок» одновременно. Он собирает их в массив, создает их для этого пользователя, но ловит любые ошибки, чтобы пользователь мог вернуться и исправить их. Как я могу игнорировать создание каких-либо ссылок, которые уже существуют для этого пользователя? Я знаю, что могу использовать validates_uniqueness_of с областью действия для этого пользователя, но я бы предпочел просто полностью игнорировать его создание. Вот мой контроллер:

@ links = params [: ссылки] .values.collect {| ссылка | current_user.links.create (ссылка) } .reject {| p | p.errors.empty? }

У каждой ссылки есть URL, поэтому я подумал о том, чтобы проверить, существует ли этот link.url для этого пользователя, но я не совсем уверен, как и где это сделать. Должен ли я прикрепить это на свой контроллер как-то? Или это должен быть новый метод в модели, такой как в обратном вызове before_validation? (Примечание: эти "ссылки" не являются вложенными, но они принадлежат: user_to:).

Итак, я хотел бы просто иметь возможность игнорировать создание этих ссылок, если это возможно. Например, если пользователь отправляет 5 ссылок, но 2 из них уже существуют для него, то я бы просто хотел, чтобы эти 2 игнорировались, а остальные 3 были созданы. Как мне это сделать?

Редактировать: Благодаря Кандада, я сейчас использую это:

@ links = Титулы [: ссылки] .values.collect.reject { | Ссылка | current_user.links.exists? (: URL => ссылка [: URL])}

@ links = @ links.collect {| link | current_user.links.create (ссылка) } .reject {| p | p.errors.empty? }

Итак, я разделил их, чтобы сначала проверить, существуют ли они, а затем создать те, которые не были отклонены. Есть ли лучший способ сделать это, как, может быть, объединение двух операторов увеличит производительность? Если нет, я думаю, что я очень доволен. (еще раз спасибо Кандада и Дж.)

Ответы [ 2 ]

2 голосов
/ 01 апреля 2010

Попробуйте это:

@links = current_user.links.create(params[:links].reject{ |link| 
           current_user.links.exists?(:url=>link[:url]) })

В качестве альтернативы вы можете добавить проверку уникальности в модели Link для атрибута url.

class Link
  validates_uniqueness_of :url, :scope => [:user_id]
end

В вашем контроллере:

@links = current_user.links.create(params[:links])

Возвращенный набор результатов представляет собой массив вновь созданных Link объектов. Любые ссылки, соответствующие существующим ссылкам, игнорируются.

Редактировать

Вот еще один способ сделать это за один проход.

@links = params[:links].map{|link| 
           !current_user.links.exists?(:url=> link[:url]) and
             current_user.links.create(link)}.select{|link| link and 
               link.errors.empty?}

Я все еще думаю, что вы должны установить свою уникальную проверку и впоследствии использовать этот код:

@links = current_user.links.create(params[:links]).select{|link| 
           link.errors.empty?}

В последнем подходе валидация уникальности выполняется в модели. Это гарантирует уникальность URL-адреса ссылки независимо от того, как создается ссылка.

1 голос
/ 01 апреля 2010

Отклонить существующие ссылки перед их созданием:

new_links = params[:links].reject{ |link| current_user.links.exists?(link) }

Примерно так. Не уверен насчет этого кода ...

...