我在模型上有以下代码,但是我很想找到一种方法来重构它,使其变得更小,更整洁。我也喜欢只在状态字段实际发生变化的情况下运行它。有人能指出我正确的方向。这是rails 3 BTW。
它的作用是查看名为subscription的模型上的“state”字段,如果它从一个条件更改为另一个条件,则在salesforce中进行更新。我正在寻找一种优化此代码的方法。
after_save :update_salesforce
def update_salesforce
if self.state_changed? && salesforce_client
salesforce_client.materialize("Opportunity")
o = Opportunity.find_by_breatheHR_id__c(self.subscriber_id)
if o
old_state = self.state_was
new_state = self.state
#update salesforce when accounts go active
if (old_state =='trial' || old_state == 'suspended') && new_state =='active'
o.update_attribute(:Stage__c, "Active Account")
end
#update salesforce when accounts go active
if old_state =='trial' && new_state =='suspended'
o.update_attribute(:Stage__c, "Trial Suspended")
end
#update salesforce when accounts go active
if old_state =='active' && new_state =='suspended'
o.update_attribute(:Stage__c, "Account Suspended")
end
#update salesforce when accounts go active
if old_state =='active' && new_state =='inactive'
o.update_attribute(:Stage__c, "Account Cancelled")
end
#update salesforce when accounts go active
if old_state =='trial' && new_state =='inactive'
o.update_attribute(:Stage__c, "Trial Cancelled")
end
end_of_day
end
end
仅运行它,我试过
after_save :update_salesforce, :if => self.state_changed?
但此时并不承认“自我”。
答案 0 :(得分:1)
以下是您可以应用的几种重构:
self
每次只需要设置值时,您不需要编写self
,否则Ruby将创建一个局部变量而不是调用setter方法。在您的情况下,self
的所有出现都是多余的,只是添加噪音。
您需要摆脱不必要的嵌套,它使代码更容易阅读和理解。一般来说,当前提条件失败时,您可以提前返回。例如:
def update_salesforce
if state_changed? && salesforce_client
o = Opportunity.find_by_breatheHR_id__c(subscriber_id)
if o
# perform hard work
end
end
end
# becomes
def update_salesforce
return unless state_changed? && salesforce_client
o = Opportunity.find_by_breatheHR_id__c(subscriber_id)
return unless o
# perform hard work
end
:if
选项在检查状态是否已更改的特殊情况下,您可以使用:if
回调中的after_save
选项。你非常接近,但你需要提供方法名称作为符号,或使用proc。对于像这样的简单情况,您可以使用符号形式:
after_save :update_salesforce, :if => :state_changed?
另一种情况也很特殊,因为你可以使用语句修饰符return
来标记行尾的or
。这实际上是or
的预期用途,而您应该始终使用||
进行布尔运算。转型是
x = do_something
return unless x
# becomes
x = do_something or return
当您查看该方法时,大多数行会一遍又一遍地重复,只有轻微的变化。您可以做的是将状态转换逻辑提取到单独的方法中。在这种方法中,你可以拉出一个技巧并将变化的状态放入一个哈希值,从中选择适当的值。键是表示转换的数组,值是Stage__c
字段的新值。返回nil
时,不得更新Stage__c
。例如:
def new_stage_from_state_transition(old_state, new_state)
{
['suspended', 'active' ] => 'Active Account',
['trial' , 'active' ] => 'Active Account',
['trial' , 'suspended'] => 'Trial Suspended',
['active' , 'suspended'] => 'Account Suspended',
['active' , 'inactive' ] => 'Account Cancelled',
['trial' , 'inactive' ] => 'Trial Cancelled'
}[[old_state, new_state]]
end
所有这些都会产生更清晰,重复性更低的代码:
after_save :update_salesforce, :if => :state_changed?
def update_salesforce
return unless salesforce_client
o = Opportunity.find_by_breatheHR_id__c(subscriber_id) or return
new_stage = new_stage_from_state_transition(state_was, state) or return
o.update_attribute(:Stage__c, new_stage)
end
def new_stage_from_state_transition(old_state, new_state)
{
['suspended', 'active' ] => 'Active Account',
['trial' , 'active' ] => 'Active Account',
['trial' , 'suspended'] => 'Trial Suspended',
['active' , 'suspended'] => 'Account Suspended',
['active' , 'inactive' ] => 'Account Cancelled',
['trial' , 'inactive' ] => 'Trial Cancelled'
}[[old_state, new_state]]
end
答案 1 :(得分:0)
#update salesforce when accounts go active
if new_state =='active'
o.update_attribute(:Stage__c, "Active Account")
else
what = old_state == 'active' ? "Account" : "Trial"
change = new_state == 'inactive' ? "Canceled" : "Suspended"
o.update_attribute(:Stage__c, "#{what} #{change}" )
end