0

我有一个 User 和一个 StripeCustomer 模型。每个用户嵌入一个并接受_nested_attributes_for StripeCustomer。

创建新用户时,我总是创建一个相应的 StripeCustomer,如果您提供 CC 或优惠券代码,我会创建一个订阅。

在我的 StripeCustomer 中:

attr_accessible :coupon_id, :stripe_card_token

我想做的是,如果优惠券无效,请执行以下操作:

errors.add :coupon_id, "bad coupon id"

因此,正常的 rails 控制器模式如下:

if @stripe_customer.save
    ....
else
    ....
end

会工作的。并且能够使用普通的 rails field_with_errors 东西来处理不良优惠券。

所以问题是,我应该在哪个活动记录回调处调用 Stripe::Customer.create 并保存 stripe_customer_token?

我在 before_create 上使用了它,因为我希望它只有在您真的要保留记录时才完成。但这会做一些奇怪的事情吗?更糟糕的是,如果您要通过用户创建它,即使您在 before_create 回调中执行 errors.add ,用户和 StripeCustomer 的保存实际上也会成功!我认为问题在于,只有在添加错误并在 before_validation 处返回 false 时,保存才会失败。

最后一部分我不确定这是否是一个 mongoid 问题。

我可以将它移动到 before_validation :on => :create 但即使我刚刚调用了valid,它也会创建一个新的 Stripe::Customer?我不想要。

无论如何,我一般都很好奇任何由远程服务记录支持或链接到的模型的最佳实践以及如何处理错误。

4

2 回答 2

1

Ok here is what I did, I split the calls to stripe into 2 callbacks, one at before_validation and one before_create (or before_update).

In the before_validation, I do whatever I can to check the uncontrolled inputs (directly from user) are valid. In the stripe case that just means the coupon code so I check with stripe that it is valid and add errors to :coupon_code as needed.

Actually creating/updating customers with stripe, I wait to do until before_create/before_update (I use two instead of just doing before_save because I handle these two cases differently). If there is an error then, I just don't handle the exception instead of trying to add to errors after validation which (a) doesn't really make any sense and (b) sort of works but fails to prevent saves on nested models (in mongoid anyway, which is very bad and strange).

This way I know by the time I get to persisting, that all the attributes are sound. Something could of course still fail but I've minimized my risk substantially. Now I can also do things like call valid? without worrying about creating records with stripe I didn't want.

In retrospect this seems pretty obvious.

于 2012-07-09T17:03:43.473 回答
0

我不确定我是否完全理解这种情况。你写了:

每个用户嵌入一个并接受_nested_attributes_for StripeUser

您是说 StripeCustomer 吗?

所以你有一个用户有一个持有优惠券信息的客户?

如果是这样,我认为在用户中接受客户的嵌套属性就足够了,将验证放在客户代码中,就是这样。看这里

如果我把你的问题弄错了,请告诉我...

于 2012-07-07T05:47:44.790 回答