find_or_create_by in Rails 3 and updating for creating records

好久不见. 提交于 2019-11-27 18:53:23
fl00r

Here is two approaches.

First you can extend Available with exact method you need:

def self.find_or_create_by_room_id_and_bookdate_and_source(room_id, bookdate, source, &block)
  obj = self.find_by_room_id_and_bookdate_and_source( room_id, bookdate, source ) || self.new(:room_id => room_id, :bookdate => bookdate, :source => source)
  yield obj
  obj.save
end

usage

Available.find_or_create_by_room_id_and_bookdate_and_source(room.id, (params[:date].to_date)+index, data.class.to_s) do |c|
  c.price = night.price
  c.spots = night.spots
end

This is awkward. So for being more flexible you can create update_or_create_by... method for ActiveRecord using method_missing magic:

class ActiveRecord::Base
  def self.method_missing(method_id, *args, &block)
    method_name = method_id.to_s
    if method_name =~ /^update_or_create_by_(.+)$/
      update_or_create($1, *args, &block)
    else
      super
    end
  end
  def self.update_or_create(search, *args, &block)
    parameters = search.split("_and_")
    params = Hash[ parameters.zip(args) ]
    obj = where(params).first || self.new(params)
    yield obj
    obj.save
    obj
  end
end

So now you can use it:

Available.update_or_create_by_id_and_source(20, "my_source") do |a|
  a.whatever = "coooool"
end
Tian Chen

Actually, there is a way without any hacking. Instead of find_or_create_by you can use find_or_initialize_by and set updated atributes with tap

Available.find_or_initialize_by_room_id_and_bookdate_and_source(
  room.id, 
  (params[:date].to_date)+index, 
  data.class.to_s#
).tap do |a|
  a.price = night.price
  a.spots = night.spots
end.save!

Initially this can seems cluttered, but it is doing exactly what you asked for. Find the record, instanciate it if not found and update atributes. this could be called "find_and_update_or_create_by", fortunatelly nobody did that. ;) Hope this help.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!