On Tuesday, October 15, 2013 12:47:30 PM UTC-7, Rodrigo Rosenfeld Rosas 
wrote:
>
>  Em 15-10-2013 16:38, Jeremy Evans escreveu:
>  
> On Tuesday, October 15, 2013 10:07:53 AM UTC-7, Rodrigo Rosenfeld Rosas 
> wrote: 
>>
>> Is there any alternative in Sequel for ActiveRecord's 
>> find_or_initialize_by class method? 
>>
>>  
>> http://edgeapi.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-find_or_initialize_by
>>  
>> http://guides.rubyonrails.org/active_record_querying.html#find-or-initialize-by
>>  
>>  I could only find find_or_create:
>>
>>  
>> http://sequel.rubyforge.org/rdoc/classes/Sequel/Model/ClassMethods.html#method-i-find_or_create
>>  
>>  Thanks in advance,
>> Rodrigo.
>>
>>   
> Nope, there isn't an alternative method.  You can do:
>
>   object = Model.find(...) || Model.new(...)
>  
>
> Yes, I'm using the exact same implementation as AR in a custom plugin:
>
> module ClassMethods
>   def find_or_initialize(attributes, &block)
>     find(attributes) || new(attributes, &block)
>   end
> end
>
>  I'm not sure this method is common enough to be warrant adding to 
> Sequel::Model itself.  As it is trivial to implement yourself, there 
> doesn't seem to be a good reason to add it.
>  
>
> I believe it's quite common. This is the second time I felt the need for 
> it in my application.
>
> This is very common in some save actions where you either update or create 
> a record but where find_or_create is not suitable.
>
> Also, implementation of find_or_create is also trivial, but it's part of 
> the core.
>
> Here's a typical usage:
>
> comment = FieldValueComment.find_or_initialize(transaction_id: 
> params[:transaction_id].to_i, field_id: params[:field_id].to_i)
> # you can't use find_or_create because date and message are required 
> columns
> comment.date = Time.now
> comment.message = params[:message].strip
> comment.save raise_on_failure: true
> render :ok
>
> It seems find_or_initialize_by is used a lot in open-source code in GitHub:
>
> https://github.com/search?q=find_or_initialize_by&ref=cmdform&type=Code
>
> " We've found 2,807 code results"
>
> Hopefully this could be part of core Sequel.
>

find_or_create is significantly more popular:

https://github.com/search?q=find_or_create&ref=cmdform&type=Code

 "We've found 8,397 code results" 
Yes, there are a few places where find_or_initialize_by will work where 
find_or_create will not, namely, where there are attributes that must be 
present to save that are not in the provided hash.  However, there are 
probably a large number of helper methods than can be added that are of 
similar usefulness.  One of Sequel's design philosophies is to keep a small 
core.  If I added all of the potentially useful helper methods to core, 
Sequel would end up bloated, and I don't want that.  I don't think the 
benefits are worth the costs in this case.

Now, I could be wrong about this.  Maybe, in spite of the fact that nobody 
has previously asked about this method in the 5+ years I have been 
maintaining Sequel, it is wildly popular in the Sequel community, and 
everyone just adds it locally, but never thought to ask me to include it.  
If that is the case, please speak up.

FWIW, instead a find_or_initalize_by, I think a better API would be 
something like:

  def update_or_create(attrs, update_attrs=nil)
    obj = find(attrs) || new(attrs)
    obj.set(update_attrs) if update_attrs
    yield obj if block_given?
    obj.save_changes
  end

  FieldValueComment.update_or_create(transaction_id: 
params[:transaction_id].to_i, field_id: params[:field_id].to_i) do |comment|
    comment.date = Time.now
    comment.message = params[:message].strip
  end
  # or 
  FieldValueComment.update_or_create({transaction_id: 
params[:transaction_id].to_i, field_id: params[:field_id].to_i}, {date: 
Time.now, message: params[:message].strip}) 

An object retrieved via find_or_initialize_by is virtually always going to 
end with saving the object, so it's better to have a method that is 
designed specifically for that use case.

Thanks,
Jeremy

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to