Разрешить только одно обновление для конкретного параметра? - PullRequest
0 голосов
/ 29 ноября 2018

Как сделать так, чтобы после заполнения параметра он не мог быть обновлен или отредактирован снова?

Проблема: У меня есть параметр: видео, которое когда-то было заполненоэто будет взимать плату с клиента.Я хочу сделать так, чтобы после заполнения он не мог обновляться или редактироваться снова.

Я предпринял превентивные меры на стороне просмотра, что после загрузки видео форма редактирования / обновления скрыта и можетне будет создан снова, но я заметил одну вещь: если по какой-либо причине не удается выполнить обновление, можно вернуться на страницу и снова заполнить форму обновления (даже если видео загружено), таким образом снова взимая плату с клиента.

Как это работает: Покупатель создает заказ, идентификатор полосы создается, как только продавец выполнит заказ (загрузив файл или видео), сбор будет снят.

  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)
        begin
                      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),
                        }
                      })
                    rescue Stripe::CardError => e
                      charge_error = e.message
                    end
          @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 }
        elsif
          if charge_error
            flash[:error] = charge_error
            redirect_to user_order_path([@user, @order])
          else
          format.html { render :edit }
          format.json { render json: @order.errors, status: :unprocessable_entity }
        end
      end
    end
  end
private

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

Не стесняйтесь, дайте мне знать, если есть лучший способ проверить обвинения на клиенте.Больше всего меня беспокоит то, что с клиента взимается плата более одного раза, потому что продавец либо ошибается, либо злонамерен, и т. Д. Я хочу гарантировать, что с клиента будет взиматься плата только один раз.Единственный способ, о котором я могу думать, - это разрешить только одно обновление для столбца видео.

Либо это, либо создание отдельной таблицы для видео с уникальным идентификатором order_id для каждого идентификатора таблицы видео.

ОБНОВЛЕНИЕ

Я закончил тем, что сделал следующее, которое работает ... Если у кого-то есть идеи о лучшем способе, я открыт для предложений!

def charge_update
    respond_to do |format|
    if @order.video.present?
      format.html { redirect_to ([@user, @order]), notice: 'Order already completed!.' }
      format.json { render :show, status: :ok, location: @order }
    else
        @amount = (@order.order_price).to_i * 100
        @amount_seller = (@order.order_price).to_i * 75
        if @order.update(order_charge)
          begin
...
...
...
end

Ответы [ 4 ]

0 голосов
/ 01 декабря 2018

Я закончил тем, что создал контроллер только для загрузки видеофайлов.

Таким образом я могу создать загрузку с кодом оплаты в процессе создания, а затем разрешить обновление без необходимости отделять обновления..

Это суть контроллера до сих пор:

def create

    @video_order = VideoOrder.new(video_order_params)
    @order = Order.find(params[:order_id])

    @video_order.order_id = @order.id

    respond_to do |format|
      if @order.video_order.present?
          format.html { redirect_to @order, notice: 'Already complete dog!.' }
          format.json { render :show, status: :created, location: @video_order }
        else

      if @video_order.valid?
        begin
          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),
            }
          })
        rescue Stripe::CardError => e
          charge_error = e.message
        end
        if charge_error
          flash[:error] = charge_error
          redirect_to '/'
        else

          if @video_order.save
            @order.update_column(:order_status, 2)
            format.html { redirect_to @order, notice: 'Video order was successfully created.' }
            format.json { render :show, status: :created, location: @video_order }
          else
            format.html { render :new }
            format.json { render json: @video_order.errors, status: :unprocessable_entity }
          end
        end
      end
    end
  end
end

  # PATCH/PUT /video_orders/1
  # PATCH/PUT /video_orders/1.json
  def update
    respond_to do |format|
      if @video_order.update(video_order_params)
        format.html { redirect_to user_order_path([@user, @order]), notice: 'Video order was successfully updated.' }
        format.json { render :show, status: :ok, location: @video_order }
      else
        format.html { render :edit }
        format.json { render json: @video_order.errors, status: :unprocessable_entity }
      end
    end
  end

У меня также есть профилактические меры в методе создания на всякий случай.

0 голосов
/ 29 ноября 2018

Я бы реализовал обратный вызов с ActiveModel::Dirty, чтобы инициировать откат любого изменения после изменения значения столбца на что-либо не с пустого или нулевого значения.

class Amount < ActiveRecord::Base
  include ActiveModel::Dirty

  before_save :check_video

  attr_accessor :video # or whatever your video attribute is

  private

  def check_video
    false if video_changed? && !video_was.nil? # or empty or whatever
    true
  end
end
0 голосов
/ 29 ноября 2018

Я бы позаботился о том, чтобы на уровне модели запись больше не могла обновляться после ее успешного создания.

Одним из простых способов может быть переопределение используемого метода readonly?.Rails для проверки внутренних записей только для чтения:

# in your model
def readonly?
  super || video.present? && persisted?
end

Вызов save для экземпляра только для чтения вызовет исключение ActiveRecord::ReadOnlyRecord.

С этим методом вы можетенапишите if @order.readonly? в вашем контроллере и просмотрите, чтобы проверить, можно ли обновлять @order.

0 голосов
/ 29 ноября 2018

Лучший способ - создать таблицу с этими значениями

order_id 
video_id 
user_id 
charged (Boolean Value )

после того, как клиент сделал заказ и оплатил его, вы можете заполнить эти значения и сделать начисленное значение истинным.

вы можете проверить, сделал ли он заказ на это видео раньше или нет, прежде чем делать новый платеж за него снова.

вот пример модели, которую вы можете сделать для этого

  class CustomerOrder < ActiveRecord::Base
  belongs_to :customer
  belongs_to :order
  belongs_to :video      
  end 

перед тем, как клиент сделает новый заказ, вы можете проверить, есть ли какое-либо отношение

   @customerorder =CustomerOrder.where(video_id: @video.id , user_id: @user.id , charged :true )
...