我应该在一个控制器中创建多个控制器还是多个更新方法?

时间:2018-11-25 23:44:12

标签: ruby-on-rails ruby

问题:我有一个控制器,我想将更新动作分为3个单独的更新动作...更新所有参数(减去其他更新动作),更新以更改订单状态(创建,取消,收费)和收费更新(仅在将文件上传到订单后收费)

问题:您能帮我指导和指导我完成该方向吗?

我应该如何以最有效和“正确”的方式进行此操作?

  1. 我是否应该再创建2个控制器(因为我需要3个更新),一个用于更改订单状态,一个用于收费,并让它们继承OrderController?

  2. 还是可以在一个控制器中执行3个更新操作?我试过了,但没弄清楚

这是我“解决”它的方法,但是有时似乎运行不顺畅,有时我注意到将文件上传到订单时,它开始循环播放和/或比将所有文件都放在一个目录下需要更长的时间定义的参数方法:

  def update
    respond_to do |format|
      if @order.update(order_status)
        if user_signed_in?
          format.html { redirect_to ([@user, @order]), notice: 'Order was successfully order_status.' }
          format.json { render :show, status: :ok, location: @order }
        else
          format.html { render :edit }
          format.json { render json: @order.errors, status: :unprocessable_entity }
        end
      end
        if @order.update(order_charge)
          @amount = (@order.order_price).to_i * 100
          @amount_seller = (@order.order_price).to_i * 75
          if @order.update(order_charge)
            if current_user.seller?
                          charge = Stripe::Charge.create({
                            :amount      => @amount,
                            :description => 'Rails Stripe customer',
                            :currency    => 'usd',
                            :customer => @order.stripe_customer_token,
                            :destination => {
                              :amount => @amount_seller ,
                              :account => (@order.seller.stripe_token),
                            }
                          })
              @order.order_status = "charged"
              format.html { redirect_to ([@user, @order]), notice: 'Order was successfully uploaded.' }
              format.json { render :show, status: :ok, location: @order }
            else
              format.html { render :edit }
              format.json { render json: @order.errors, status: :unprocessable_entity }
            end
          end
        end
        if @order.update(order_params)
          if user_signed_in?
            format.html { redirect_to ([@user, @order]), notice: 'Order was successfully updated.' }
            format.json { render :show, status: :ok, location: @order }
          else
            format.html { render :edit }
            format.json { render json: @order.errors, status: :unprocessable_entity }
          end
          if buyer_signed_in?
            format.html { redirect_to ([@user, @order]), notice: 'Order was successfully updated.' }
            format.json { render :show, status: :ok, location: @order }
          else
            format.html { render :edit }
            format.json { render json: @order.errors, status: :unprocessable_entity }
          end
        end
      end
    end


  private

    def set_order
      @order = Order.find(params[:id])
    end


    def order_params
      params.require(:order).permit(:name, :email, :image, :video, :description)
    end

    def order_status
      params.require(:order).permit(:order_status)
    end

    def order_charge
      params.require(:order).permit(:video)
    end
...
end

从技术上讲这是可行的,但速度或速度并不理想。当我上传视频时,它会给我order_status消息,这是因为当视频上传时,我会更改订单状态。但是从某种意义上说,它仍然有效。

有没有人开发过一个应用程序,需要在一个控制器和一个模型下执行多个更新操作,并且找到了执行该更新的最佳方法?

尽管上面的代码“有效”,但我被告知效率不高,我应该再创建2个控制器来执行我想做的事情。我想我会先来这里,然后再进行此操作,以让其他人根据他们的经验获得意见,如果他们有与此问题相似的应用程序。

或者除了上述1和2之外,您还有其他想法吗?

(上面的更新操作尚未完成,例如order_status。但是我最担心的是应该如何实际执行此操作。)

2 个答案:

答案 0 :(得分:1)

解决此问题的一种方法是只使用一种app.post('/ownerPanel', (req, res) => { try { let addBook = books.books.addBookOwner(req.body.book_title, req.body.author, req.body.price, req.body.subject, req.body.isbn, req.body.Vendor, req.body.Owner, connection, res); console.log("addBook", addBook); if (addBook) { console.log("in the if in app vendor"); books.books.renderOwner(connection, res); } else { let deleteBook = books.books.deleteBook(req.body.isbn, connection, res); console.log("deleteBook", deleteBook); if (deleteBook) { console.log("in the if in app post "); books.books.renderOwner(connection, res); } else { console.log("didn't match either if or else if conditions"); } } books.books.renderOwner(connection, res); } catch(e) { console.log("ownerPanel exception", e); res.sendStatus(500); } }) 方法并删除order_paramsorder_charge,因为无论哪种情况,仅更新一个资源。正如您所说,仅在一种情况下,用户在上传文件时才需要向用户收费,因此请在 controller 中使用助手方法来负责向用户收费。

order_status

在您的更新方法内部,只需更新订单并根据需要向用户收费。就像这样

def charge_amount
    @amount = (@order.order_price).to_i * 100
    @amount_seller = (@order.order_price).to_i * 75
    if current_user.seller?
      charge = Stripe::Charge.create({
                        :amount      => @amount,
                        :description => 'Rails Stripe customer',
                        :currency    => 'usd',
                        :customer => @order.stripe_customer_token,
                        :destination => {
                          :amount => @amount_seller ,
                          :account => (@order.seller.stripe_token),
                        }
                      })
      @order.order_status = "charged"
    end
end

采用这种方法,代码将缩小大小并分离逻辑,并且更易于调试。我希望这能回答您的问题,或者至少为您提供一些指导。

更新 如果需要单独的操作,只需在控制器中创建三个方法,然后根据参数的类型在def update respond_to do |format| if user_signed_in? #this could be moved to a `before_action` that authenticates the user if @order.update(order_status) if order_params[:video].present? charge = charge_amount end format.html { redirect_to ([@user, @order]), notice: 'Order was successfully order_status.' } format.json { render :show, status: :ok, location: @order } else format.html { render :edit } format.json { render json: @order.errors, status: :unprocessable_entity } end end end end 操作中调用适当的方法。

答案 1 :(得分:0)

我最终还是这样做了...多亏了我早些时候找到的一篇SO帖子...

订单控制器:(与更新操作分开:)

def charge_update
    respond_to do |format|
      @amount = (@order.order_price).to_i * 100
      @amount_seller = (@order.order_price).to_i * 75
      if @order.update(order_charge)
                      charge = Stripe::Charge.create({
                        :amount      => (@order.order_price).to_i * 100,
                        :description => 'Rails Stripe customer',
                        :currency    => 'usd',
                        :customer => @order.stripe_customer_token,
                        :destination => {
                          :amount => @amount_seller ,
                          :account => (@order.seller.stripe_token),
                        }
                      })
          @order.update_column(:order_status, 2)
          format.html { redirect_to ([@user, @order]), notice: 'Order was successfully uploaded.' }
          format.json { render :show, status: :ok, location: @order }
        else
          format.html { render :edit }
          format.json { render json: @order.errors, status: :unprocessable_entity }
        end
      end
  end

路线:

 resources :orders do
    member do
      patch :charge_update
      put :charge_update
    end
  end

对于视图中的上传:

<%= form_for([@listing, @order], :url => charge_update_order_path ) do |form| %>
...
<%= form.file_field :video %>
...
<%= form.submit "Upload", class: "btn btn-success"  %>

控制器的其余部分:(专用部分)

private

def order_charge
      params.require(:order).permit(:video, :order_status)
    end

现在,上传视频操作是独立的,并且运行速度更快。我在更新订单状态以取消订单方面并没有做同样的事情,在进行更多测试后,我可能会也可能不会。与其他参数区分开来,充电方面是最重要的事情。