user.save上的堆栈级别太深

时间:2015-08-20 09:21:18

标签: ruby-on-rails rails-activerecord

我想在创建一个确认代码时为其分配一个确认代码。在保存更新它们之前,我还标题了一些列。所以我的user.rb看起来像这样(可能有点乱):

// user.rb
*** some code ***
before_save { titleize_column(:name)
                titleize_column(:surname)
                capitalize_column(:complaints) 
                capitalize_column(:education)
                capitalize_column(:job)
                capitalize_column(:complaintsdetails)
                capitalize_column(:prediagnosis)
                capitalize_column(:existingdiagnosis)
                capitalize_column(:knownilnessesother)
                capitalize_column(:usedmedicine)
                capitalize_column(:operation)
                capitalize_column(:trauma)
                capitalize_column(:allergy)
                capitalize_column(:otherhabits)
                capitalize_column(:motherother)
                capitalize_column(:fatherother)
                capitalize_column(:siblingsother)
              }
  before_save :generate_confirmation_code
protected
    def generate_confirmation_code
      unless self[:confirmed]
        if(self[:type] == 'Patient')
          update_attribute :confirmation_code, SecureRandom.urlsafe_base64(20)
          update_attribute :confirmed, false
        else
          update_attribute :confirmed, true
        end
      end
    end

protected
    def capitalize_column(attr)
      unless self[attr].nil?
        self[attr] = Unicode::capitalize self[attr]
      end
    end

  protected
    def titleize_column(attr)
      unless self[attr].nil?
        words = self[attr].split
        words.each_with_index do |v,i|
          words[i] = Unicode::capitalize v
        end
        self[attr] = words.join(" ")
      end
    end

我正在使用单独的方法来标题化和大写列,因为在第一次创建用户时它们可能是nil,所以我在这些方法中检查它是否为null。这种结构在具有强参数的正常注册时工作正常。但是,如果我尝试使用下面的方法使用twitter注册,它会给我错误“堆栈级别太深”,我可以看到它从应用程序跟踪调用了generate_confirmation_code 123次然后发生了这些:< / p>

app / models / user.rb:83:in each' app/models/user.rb:83:in each_with_index' app / models / user.rb:83:在titleize_column' app/models/user.rb:20:in块中' app / models / user.rb:64:in generate_confirmation_code' (x123 times) app/models/user.rb:101:in from_omniauth' app / controllers / socials_controller.rb:4:在'create'

// method for signing up/logging in a user from twitter

  class << self
    def from_omniauth(auth_hash)
      if exists?(uid: auth_hash['uid'])
        user = find_by(uid: auth_hash['uid'])
      else
        user = find_or_create_by(uid: auth_hash['uid'], provider: auth_hash['provider'], type: 'Patient')
        user.password_digest = User.digest('111111')
        user.name = auth_hash['info']['name']
        user.location = get_social_location_for user.provider, auth_hash['info']['location']
        user.avatar = auth_hash['info']['image']
        user.url = get_social_url_for user.provider, auth_hash['info']['urls']
        user.save!            // THIS IS THE LINE 101!
        conversation = Conversation.create()
        user.conversation = conversation
        admin = Admin.first
        admin.conversations << conversation
        user.progress = Progress.create(active_state:1)
      end
      user
    end

我认为我正在弄乱使用before_save不正确,但不知道如何做对。我在这里做错了什么?

2 个答案:

答案 0 :(得分:4)

update_attribute也会触发save回调,从而无限循环before_save,从而产生的堆栈级别太深。

你可以简单地在before_save回调方法中分配值,因为无论如何它们只会被保存。请参阅以下内容:

def generate_confirmation_code
  unless self[:confirmed]
    if(self[:type] == 'Patient')
      self.confirmation_code = SecureRandom.urlsafe_base64(20)
      self.confirmed = false
    else
      self.confirmed = true
    end
  end
end

答案 1 :(得分:1)

您在 $html_td = $html = $html_th = ""; $i=0; foreach ($result as $record) { $i++; $html_td .= "<tr data-Year='".$record->year."'>"; //$html_td .= "<td>".$i."</td>"; $html_td .= "<td title='".$record->recipient_name."' class='masterTooltip' >".$record->recipient_name."</td>"; $html_td .= "<td title='".$record->year."' class='masterTooltip' >".$record->year."</td>"; $html_td .= "<td title='".strtoupper($record->title)." -: ".$record->long_description."' class='masterTooltip' >".substr($record->title,0,30).'....'."</td>"; $html_td .= "<td title='".$record->sector."' class='masterTooltip' >".substr($record->sector,0,20)."</td>"; $html_td .= "<td title='".$record->region."' class='masterTooltip' >".$record->region."</td>"; $html_td .= "<td title='".$record->commitment_million_inr."' style='width:65px' class='masterTooltip' >".$record->commitment_million_inr."</td>"; if($_POST['commitment_usd_million'] == True){ $html_td .= "<td title='".$record->commitment_usd_million."' class='masterTooltip' >".$record->commitment_usd_million."</td>"; } if($_POST['expenditure_inr_million'] == True){ $html_td .= "<td title='".$record->expenditure_inr_million."' class='masterTooltip' >".$record->expenditure_inr_million."</td>"; } if($_POST['expenditure_usd_million'] == True){ $html_td .= "<td title='".$record->expenditure_usd_million."' class='masterTooltip' >".$record->expenditure_usd_million."</td>"; } if($_POST['aiddata_purpose_code'] == True){ $html_td .= "<td title='".$record->aiddata_purpose_code."' class='masterTooltip' >".$record->aiddata_purpose_code."</td>"; } if($_POST['aiddata_purpose_description'] == True){ $html_td .= "<td title='".$record->aiddata_purpose_description."' class='masterTooltip' >".$record->aiddata_purpose_description."</td>"; } $html_td .= "</tr>"; } echo "response";die(); 回调方法中调用update_attribute,而只是为属性分配值。方法签名before_save应如下所示 -

generate_confirmation_code