简体   繁体   English

Rails before_action需要很长时间

[英]Rails before_action that takes long time

I'm using something like this in my Controller class: 我在Controller类中使用这样的东西:

before_action :do_something, only: [:new, :create]

def new
   @myModel = MyModel.new
end

def create
   @myModel = MyModel.create_with_data(params)

   respond_to do |format|
     if @myModel.errors.empty?
        format.html { redirect_to @myModel, notice: 'MyModel was successfully created.' }
        format.json { render :show, status: :created, location: @myModel }
     else
        logger.error 'MyModelController: Creating mymodel failed!'
        format.html { render :new }
        format.json { render json: @myModel.errors, status: :unprocessable_entity }
     end
end

def do_something
   # Very long method
end

Now, the problem is, that my do_something method takes very long to execute. 现在,问题是,我的do_something方法需要很长时间才能执行。 If user will make mistake while creating new myModel field, he will need to wait for this method to execute, just to display him some error. 如果用户在创建新的myModel字段时会出错,他将需要等待此方法执行,只是为了向他显示一些错误。

Let's say, that I don't want front-end validation and I can't reduce the time of do_something method. 让我们说,我不想要前端验证,我不能减少do_something方法的时间。 How can I pass somehow data from do_something that executed before new method is called, so it won't be needed to execute again before create method? 如何从调用new方法之前执行的do_something中以某种方式传递数据,因此在create方法之前不需要再次执行?

I would consider using an optimistic saving approach instead. 我会考虑使用乐观的保存方法。 Much like how unconfirmed users are usually treated. 就像通常如何处理未经证实的用户一样。

You insert the record in the database but set a state which denotes that it's not a full fledged record. 您在数据库中插入记录,但设置一个状态,表示它不是一个完整的记录。 You then update the record when it is confirmed. 然后在确认时更新记录。

It gives the user quick feedback and you can free your web process from waiting for do_something . 它为用户提供快速反馈,您可以让您的Web进程免于等待do_something

class MyModel < ActiveRecord::Base
  # create an Int column named status
  # make sure it has an index and defaults to 0.
  enum status: [:unverified, :verified]
end

So, you would do something like this in your controller: 所以,你会在你的控制器中做这样的事情:

def create
  # Don't do params assignment / whitelisting in your models.
  # models should not be aware of parameters.
  @my_model = MyModel.new(my_model_params) do |m|
    # This should be handled by the DB default but 
    # this is a belt and suspenders approach to be 200% sure
    # that a record does not slip through.
    m.unverified!
  end

  if @my_model.save
    MyModelVerificationJob.perform_later(@my_model)
    respond_to do |format|
      format.html do
        flash[:notice] = "We are currently verifying..."
        redirect_to :edit, @my_model
      end
      # ...
    end
  else
    # we already know something is fishy so just render the 
    # form again.
    respond_to do |format|
      # ...
    end
  end
end 

private
  def my_model_params
    params.require(:my_model).permit(...)
  end

This example is with Rails 5 Active Jobs but you can look into Resque or Sidekiq as well. 此示例使用Rails 5 Active Jobs,但您也可以查看Resque或Sidekiq。

How exactly to handle the callback from your do_something method depends on what kind of user interaction is required. 如何从do_something方法处理回调取决于所需的用户交互类型。 If the user needs to correct a form for example you would cache the results from the background job and prompt the user to visit a page where they correct the form. 例如,如果用户需要更正表单,则会缓存后台作业的结果,并提示用户访问他们更正表单的页面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM