开发者

How do I reject if exists? for non-nested attributes?

Currently my controller lets a user submit muliple "links" at a time. It collects them into an array, creates them for that user, but catches any errors for the User to go back and fix. How can I ignore the creation of any links that already exist for that user? I know that I can use validates_uniqueness_of with a scope for that user, but I'd rather just ignore their creation completely. Here's my controller:

@links = params[:links].values.collect{ |link| current_user.links.create(link) }.reject { |p| p.errors.empty? }

Each link has a url, so I thought about checking if that link.url already exists for that user, but wasn't really sure how, or where, to do that. Should I tack this onto my controller somehow? Or should it be a new method in the model, like as in a before_validation Callback? (Note: these "links" are not nested, but they do belong_to :user.)

So, I'd like to just be able to ignore the creation of these links if possible. Like if a user submits 5 links, but 2 of them already exist for him, then I'd just like for those 2 to be ignored, while the other 3 are created. How should I go about doing this?

Edit: Thanks to Kandada, I'm now using this:

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

@links = @links.collect{ |link| current_user.links.create(link) }.reject { |p| p.errors.empty? }

So I separated the two, to first check if there are a开发者_开发知识库ny that exist, then to create those that weren't rejected. Is there a better way to do this, like maybe combining the two statements would increase performance? If not, I think I'm pretty satisfied. (thank you again Kandada and j.)


Try this:

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

Alternatively you can add an uniqueness check in the Link model for the url attribute.

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

In your controller:

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

The result set returned is an array of newly created Link objects. Any links matching the existing links are ignored.

Edit

Here is another way to do this in one pass.

@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?}

I still think you should get your unique validation working and use this code afterwards:

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

In the latter approach uniqueness validation is done in the model. This ensures link url uniqueness regardless how the link is created.


Reject the existent links before create them:

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

Somethink like this. Not sure about this code...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜