find_or_create_by在Rails 3的更新和创造纪录 [英] find_or_create_by in Rails 3 and updating for creating records

查看:223
本文介绍了find_or_create_by在Rails 3的更新和创造纪录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道我是否应该更新记录这样或者如果我失去了一些东西。

我有5列(不包括时间戳和id),其中3个是不同的,并且2将得到更新的表。在3个不同的,我会寻找或创造还有ROOM_ID,日期和来源。其他2是价格和使用点(这些改变每小时,每天等)

我的问题是,我应该先找到或创建记录,然后更新(或创建)的价格和斑点或者我可以做到这一切在一次?你可以看到两种方式,现在我做的,我不知道它实际上做了什么,我期待的。

此外,有没有任何缺点做这样的find_and_cr​​eate_by?

感谢

 私有

  高清self.parse_data(PARAMS,数据)
    data.beds.each做|床|
      房间= Room.find_or_create_room(bed.title,则params [:ID])

      #find克隆不知何故
      #puts bed.nights.first.price
      bed.nights.each_with_index做|晚上,指数|
        可用= Available.find_or_create_by_room_id_and_bookdate_and_source(
          :ROOM_ID => room.id,
          :bookdate => (PARAMS [:日期] .to_date)+指数,
          :源=> data.class.to_s#,
          #:价格=> night.price
        )
        #available.price = night.price
        #available.spots = night.spots
        #available.save
      结束

    结束
 

解决方案

下面是两种方法。

<一个href="http://stackoverflow.com/questions/5160073/best-way-to-find-or-create-by-id-but-update-the-attributes-if-the-record-is-found/5160233#5160233">First你可以扩展可用有确切的方法,你需要:

 高清self.find_or_create_by_room_id_and_bookdate_and_source(ROOM_ID,bookdate,来源和放大器;块)
  OBJ = self.find_by_room_id_and_bookdate_and_source(ROOM_ID,bookdate,源)|| self.new(:ROOM_ID =&GT; ROOM_ID,:bookdate =&GT; bookdate,:源=&GT;源)
  产量OBJ
  obj.save
结束
 

用法

  Available.find_or_create_by_room_id_and_bookdate_and_source(room.id,(PARAMS [:日期] .to_date)+指数,data.class.to_s)办| C |
  c.price = night.price
  c.spots = night.spots
结束
 

这是尴尬的。因此,对于更加灵活的,你可以为的ActiveRecord 创建 update_or_create_by ... 方法,使用 method_missing的魔法:

 类的ActiveRecord :: Base的
  高清self.method_missing(method_id,*的args,&安培;块)
    方法_ = method_id.to_s
    如果方法_ =〜/^update_or_create_by_(.+)$/
      update_or_create($ 1,*的args,&安培;块)
    其他
      超
    结束
  结束
  高清self.update_or_create(搜索,*的args,&安培;块)
    参数= search.split(_ and_)
    PARAMS =哈希[parameters.zip(参数)]
    OBJ =其中(PARAMS)。首先|| self.new(PARAMS)
    产量OBJ
    obj.save
    OBJ
  结束
结束
 

所以,现在你可以使用它:

  Available.update_or_create_by_id_and_source(20,my_source)做| A |
  a.whatever =coooool
结束
 

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 distinct, and 2 which will get updated. The 3 distinct which I will find or create by are room_id, date, and source. The other 2 are price and spots available (these change hourly, daily etc.)

My question is, should I first find or create the record, then update (or create) the price and spots or can I do it all at once? You can see the two ways I'm doing it now, and I'm not sure if its actually doing what I'm expecting.

Also, is there any downside to do a find_and_create_by like this?

Thanks

  private

  def self.parse_data(params,data)
    data.beds.each do |bed|
      room = Room.find_or_create_room(bed.title, params[:id])

      #find clones somehow
      #puts bed.nights.first.price
      bed.nights.each_with_index do |night,index|
        available = Available.find_or_create_by_room_id_and_bookdate_and_source(
          :room_id => room.id, 
          :bookdate => (params[:date].to_date)+index, 
          :source => data.class.to_s#,
          #:price => night.price
        )
        #available.price = night.price
        #available.spots = night.spots
        #available.save
      end

    end

解决方案

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

这篇关于find_or_create_by在Rails 3的更新和创造纪录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆