Best way to find_or_create_by_id but update the attributes if the record is found

前端 未结 7 1444
情书的邮戳
情书的邮戳 2021-01-06 03:50

I\'m looking for a clean way to create a record with a set of attributes if the record does not exist and - if the record do exist - to update its attributes. I love the syn

7条回答
  •  天涯浪人
    2021-01-06 04:07

    I have coded this finders that can be used for different scenarios.

    The most important thing is, that it removes the parameter :id on create and update.

    Creating a model with :id can cause problems with MySql or PostgreSQL because Rails uses the auto sequence number of the database. If you create new model instances with an :id you can get a UniqueViolation: ERROR: duplicate key value violates unique constraint.

    # config/initializers/model_finders.rb
    class ActiveRecord::Base
    
      def self.find_by_or_create(attributes, &block)
        self.find_by(attributes) || self.create(attributes.except(:id), &block)
      end
    
    
      def self.find_by_or_create!(attributes, &block)
        self.find_by(attributes) || self.create!(attributes.except(:id), &block)
      end
    
    
      def self.find_or_create_update_by(attributes, &block)
        self.find_by(attributes).try(:update, attributes.except(:id), &block) || self.create(attributes.except(:id), &block)
      end
    
    
      def self.find_or_create_update_by!(attributes, &block)
        self.find_by(attributes).try(:update!, attributes.except(:id), &block) || self.create!(attributes.except(:id), &block)
      end
    
    
      def self.find_by_or_initialize(attributes, &block)
        self.find_by(attributes) || new(attributes.except(:id), &block)
      end
    
    end
    

提交回复
热议问题