I have a form for @topic that contains two fields, name(string) visible(boolean) When the user submits the form, I want to manipulate the contents of the attribute :name (which I am able to do - but it''s the next part I''m stuck on) -and then- see if a record with the contents of :name already exists -if it already exists- I want to simple add my user association to it (which I can do by: current_user.topics << @topic) -if it does not exist- then I want to create it as normal find_or_create_by_name(params:topic) doesn''t seem to work... are there any other ways to achieve this? (nube alert!) Thanks in advance. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Philip Hallstrom
2010-Dec-16 01:05 UTC
Re: Best way to do a find_by_or_create based on an attribute?
On Dec 15, 2010, at 4:50 PM, Aston J. wrote:> I have a form for @topic that contains two fields, name(string) > visible(boolean) > > When the user submits the form, I want to manipulate the contents of the > attribute :name (which I am able to do - but it''s the next part I''m > stuck on) > > -and then- > see if a record with the contents of :name already exists > > -if it already exists- > I want to simple add my user association to it (which I can do by: > current_user.topics << @topic) > > -if it does not exist- > then I want to create it as normal > > find_or_create_by_name(params:topic) doesn''t seem to work... are there > any other ways to achieve this? > > (nube alert!)If it were me I''d be clear about what I''m doing... name = params[:topic][:name] # manipulate name here... @topic = Topic.find_or_create_by_name(name) current_user.topics << @topic Only thing i''m not sure about is what you want to do with ''visible''... -philip -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-16 01:08 UTC
Re: Best way to do a find_by_or_create based on an attribute?
Aston J. wrote in post #968740:> I have a form for @topic that contains two fields, name(string) > visible(boolean) > > When the user submits the form, I want to manipulate the contents of the > attribute :name (which I am able to do - but it''s the next part I''m > stuck on) > > -and then- > see if a record with the contents of :name already exists > > -if it already exists- > I want to simple add my user association to it (which I can do by: > current_user.topics << @topic) > > -if it does not exist- > then I want to create it as normal > > This is so I don''t end up with duplicate ''topics'' in my DB. > > find_or_create_by_name(params:topic) doesn''t seem to work...Did you mean find_or_create_by_name(params[:topic][:name])? And what do you mean by "doesn''t seem to work"? In general, it''s best if you describe what happened as clearly as possible. are there> any other ways to achieve this? > > (I''m a nube) > > Thanks in advance.Best, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Aston J.
2010-Dec-16 02:00 UTC
Re: Best way to do a find_by_or_create based on an attribute?
Thanks for the reply both. Does this make it any clearer? It is my create action based on what Philip said - but it does not work: Topic(#2171041280) expected, got Hash(#2151972860) def hashtag(name) string = name return name = string if string.split.count <= 1 name = string.split.map{|w| w.capitalize}.join end def create name = params[:topic][:name] visible = params[:topic][:visible] hashtag(name) @topic = {:name => "#{name}", :visible => visible} if Topic.where(:name => "#{name}") current_user.topics << @topic redirect_to(@topic, :notice => ''Topic was successfully created.'') elsif Topic.create(@topic) current_user.topics << @topic redirect_to(@topic, :notice => ''Topic was successfully created.'') else render :action => "new" end end View as pastie here: http://pastie.org/private/kbcez0wxhfvahimdtvu64g Basically I am trying to manipulate the contents of :name and then check to see if a record already exists - to save duplicates. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Philip Hallstrom
2010-Dec-16 02:10 UTC
Re: Re: Best way to do a find_by_or_create based on an attribute?
> Thanks for the reply both. Does this make it any clearer? It is my > create action based on what Philip said - but it does not work: > Topic(#2171041280) expected, got Hash(#2151972860)You''re trying to add a hash to an AR association... Rails doesn''t like that :)> def hashtag(name) > string = name > return name = string if string.split.count <= 1 > name = string.split.map{|w| w.capitalize}.join > endTake a look at the titleize() method and get rid of hashtag entirely... http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-titleize> > def create > name = params[:topic][:name] > visible = params[:topic][:visible] > hashtag(name) > @topic = {:name => "#{name}", :visible => visible}What is visible? If visible is related to the user''s ability to see that topic then it shouldn''t be set in the topic itself. You''ll need an intermediate model (look up has many through) to handle that. Ignoring that for now... def create name = params[:topic][:name].titleize @topic = Topic.find_or_create_by_name(name) current_user.topics << topic redirect_to @topic, :notice => ''Topic was successfully created.'' end> > if > Topic.where(:name => "#{name}") > current_user.topics << @topic > redirect_to(@topic, :notice => ''Topic was successfully created.'') > elsif > Topic.create(@topic) > current_user.topics << @topic > redirect_to(@topic, :notice => ''Topic was successfully created.'') > else > render :action => "new" > end > end > > View as pastie here: http://pastie.org/private/kbcez0wxhfvahimdtvu64g > > Basically I am trying to manipulate the contents of :name and then check > to see if a record already exists - to save duplicates. > > -- > Posted via http://www.ruby-forum.com/. > > -- > You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en. >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Aston J.
2010-Dec-16 02:30 UTC
Re: Re: Best way to do a find_by_or_create based on an attribute?
Hi Philip, I tried your code: def create name = params[:topic][:name].titleize @topic = Topic.find_or_create_by_name(name) current_user.topics << @topic if @topic.save redirect_to @topic, :notice => ''Topic was successfully created.'' else render :action => "new" end end But now I get this if a topic has already been created: ''Validation failed: User has already been taken''> What is visible? If visible is related to the user''s ability to see > that topic then it shouldn''t be set in the topic itself. > You''ll need an intermediate model (look up has many through) to handle > that.Visible will be used like a soft-delete, that only admin users will be able to modify. By default all topics are visible, but if a topic is against our rules :visible will be changed to false. That way it will not show (to site visitors) and it will also catch any future violations (as it''s already been created).> Take a look at the titleize() method and get rid of hashtag entirely...Titleize only capitalizes the first letter of each word... I want to remove the space too, so it because a #hastag :-) -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Philip Hallstrom
2010-Dec-16 03:44 UTC
Re: Re: Re: Best way to do a find_by_or_create based on an attribute?
On Dec 15, 2010, at 6:30 PM, Aston J. wrote:> Hi Philip, I tried your code: > > def create > name = params[:topic][:name].titleize > @topic = Topic.find_or_create_by_name(name) > current_user.topics << @topic > if @topic.save > redirect_to @topic, :notice => ''Topic was successfully created.'' > else > render :action => "new" > end > end > > But now I get this if a topic has already been created: > > ''Validation failed: User has already been taken''That''s not the code I sent... why are you trying to save a @topic that you either a) already found or b) just created (and saved) ?? If you are concerned the topic might not get created right then... def create name = params[:topic][:name].titleize @topic = Topic.find_or_create_by_name(name) if @topic current_user.topics << @topic redirect_to @topic, :notice => ''Topic was successfully created.'' else render :action => "new" end end> >> What is visible? If visible is related to the user''s ability to see >> that topic then it shouldn''t be set in the topic itself. >> You''ll need an intermediate model (look up has many through) to handle >> that. > > Visible will be used like a soft-delete, that only admin users will be > able to modify. By default all topics are visible, but if a topic is > against our rules :visible will be changed to false. That way it will > not show (to site visitors) and it will also catch any future violations > (as it''s already been created).Ok. Then you''ll need to set that up as well in the above code after you''ve found the topic. Hey... not sure why I thought of this before, but why is your create() method *finding* a topic at all? You might want to see if there''s a better way to organize your actions...> >> Take a look at the titleize() method and get rid of hashtag entirely... > > Titleize only capitalizes the first letter of each word... I want to > remove the space too, so it because a #hastag :-)Ah yes. Missed that... name.titleize.gsub(/\s+/, '''') -philip -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Aston J.
2010-Dec-16 14:31 UTC
Re: Re: Re: Best way to do a find_by_or_create based on an attribute?
Philip Hallstrom wrote in post #968761:> ...why are you trying to save a @topic that > you either a) already found or b) just created (and saved) ??Sorry I got confused for a second and thought the create action by default uses Topic.create() by default (when it actually uses Topic.new()).> If you are concerned the topic might not get created right then... > > def create > name = params[:topic][:name].titleize > @topic = Topic.find_or_create_by_name(name) > if @topic > current_user.topics << @topic > redirect_to @topic, :notice => ''Topic was successfully created.'' > else > render :action => "new" > end > end >Thanks I tried that and it seems to be working, though it highlights a problem of when a user tries to submit the same topic. So here''s a bashat my latest code (but it still gives me an error when the same user tries to create the same topic ''Validation failed: User has already been taken'') def create name = params[:topic][:name].titleize.gsub(/\s+/, '''') @topic = Topic.find_or_create_by_name(name) if @topic if current_user.topics << @topic redirect_to @topic, :notice => ''Topic was successfully created.'' else redirect_to @topic, :notice => ''You have already added this topic'' end else render :action => "new" end end (see my next bit below to see what I''m trying to achieve) Actually I have just noticed, I have a validation for the TopicAssociation model: validates_uniqueness_of :user_id, :scope => :topic_id so I guess that''s why it is failing - but how can I handle that error more elegantly?> Ok. Then you''ll need to set that up as well in the above code after > you''ve found the topic.> Hey... not sure why I thought of this before, but why is your create() > method *finding* a topic at all? You might want to see if there''s a > better way to organize your actions...What I''m trying to do in all the code above is based on.. Having a page which will have a form with the fields ''topic'' and ''comment'' (I''ll come to dealing with comments later, just trying to get topic working right now) and neither can be blank - Users are basically adding ''topics'' that interest them (which will show on their profile), along with a comment about each topic. (And the homepage of the site will simply list the most popular topics.) So when they click submit, I want to first check that the topic doesn''t already exist (to prevent duplicate entries in the db - thus making it easier to find which topics are the most popular) and if it does, to simply add the association that they have added it (by ''current_user.topics << @topic'' ?) (and then it will add the comment to that topic too, but will deal with that later). If the topic doesn''t exist, it should get created, the association between user and topic be made, and their comment get added (again, I''ll deal with comments later). Does that make more sense about what I''m trying to do? (And why it''s all happening from one form). I don''t want to add a ''see if this topic exists first'' page, as I would rather handle all that silently. Maybe later I could add a ''live search'' for the topic name field - but that''s a future feature lol> Ah yes. Missed that... > > name.titleize.gsub(/\s+/, '''')Thanks! That''s what I wanted - and I''ll have to read up on what all of that does too :) (btw, as therean easy enough to strip anything that isn''t a-z or 1-0 from the string? That would help ensure records are unique regardless of punctuation marks etc) -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.