开发者

Using callbacks except in certain cases

I have a Rails callback for a quantitative model that updates some numbers based on recent activity, something like:

class Data < ActiveRecord::Base
before_validation :check_numbers

def check_numbers
  Check #1...
  Check #2...
  Check #3...
  Check #4...
  ...etc.
end

All of these checks add up to quite some time, often a significant fraction of a second.

If I have a controller action that only has any impact on Check #4 - how can I avoid checking #1-3? Can I, for example, pass in a variable like [4] that tells this callback to take a shortcut开发者_如何学编程?

Bonus points: is there a way to conveniently do some of this processing on the server-side after showing the candidate the next rendered page?


Doing tasks in the background that take some time on the server side can be achieved with delayed job (https://github.com/tobi/delayed_job).

As for only doing a particular check. Maybe something like the following

class Data < ActiveRecord::Base
before_validation :check_numbers

def check_numbers
  check_one if to_check.includes? 1
  check_two if to_check.includes? 2
  check_three if to_check.includes? 3
  check_four if to_check.includes? 4
  ...etc.
end

def to_check=(arr_or_checks)
  @to_check = arr_or_checks
end

def to_check
  @to_check
end

Then in your controller you could specify what needs to be checked by calling to_check([1, 3, 9]) for example.

This will add more processing to your code and will also make the Controller aware of logic that it probably should not. To get around this information leak you should make the to_check methods private and set them in methods that are used by the controllers, e.g. obj.do_x and obj.do_y may set different numbers in the to_check array.

===== UPDATE ======

Example

test = Data.find(33)
test.to_check = [1,4]
test.update_attributes(params[:test])

or test = Data.find(33) test.to_check = [1,4] test.name = "new name" test.save

Like I said I am not a huge fan of doing this explicitly in the controller. So I would try to encapsulate this in the model itself as follows.

class Data
  ...

  def update_attributes_by_admin(attributes)
    to_check = [1,4]
    update_attributes(attributes)
  end

  def update_attributes_by_reg_user(attributes)
    to_check = [1,2,3,4,...] # use all numbers here.
    update_attributes(attributes)
  end

Then back in the controller we could do something like this

def admin_action
  ...
  test = Data.find(33)
  test.update_attributes_by_admin(params[:test])
  ...
end

def reg_user_action
  ...
  test = Data.find(33)
  test.update_attributes_by_reg_user(params[:test])
  ...
end

Of course it would be safer to actually do the inverse of what I have done in this example. i.e.

check_one unless not_to_check.includes? 1

and then have not_to_check methods instead of the to_check etc.

This way all default save/update methods will do the validations and you create the ones that do not do full validations.


I think that will code is missing something

def to_check=(arr_or_checks)
   @to_check = arr_or_checks
end

Then when you want to use it it's something like:

mod = Data.find(1)
mod.to_check = [1,4]
mod.save

This would save and only check 1 and 4.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜