find_or_create_by in Rails 3 and updating for creating records

前端 未结 3 756
执念已碎
执念已碎 2020-12-05 01:17

I\'m not sure if I should be updating records this way or if I\'m missing something.

I have a table with 5 columns (not including timestamps and id) 3 of which are d

3条回答
  •  南方客
    南方客 (楼主)
    2020-12-05 01:52

    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
    

提交回复
热议问题