рельсы действительно создаются дважды, когда нет записи в определенной модели неожиданно - PullRequest
0 голосов
/ 29 апреля 2018

Guess

Странно, что это происходит, когда в базе данных нет записей.

Что я пробовал

Я сомневался, что причина была на самом деле ajax, поэтому я все удалил remote:true, но это с трудом сработало. Контроллер

def create
  @sell = current_user.orders.build(sell_params)
  @buy = current_user.orders.build(buy_params)
  if @sell.save
    flash[:success] = 'your order has successfully submitted.'
    notify_order(@sell.rate, @sell.amount, @sell.order_type)

    @sell.rate.present? ? @sell.update(order_type: 'limit_sell') : @sell.update(order_type: 'market_sell')

    fund = Fund.create_with(amount: 0, crypto_address_id: 1)
            .find_or_create_by(user_id: current_user.id, kind: @sell.pair.split('_').last)
    fund.update(in_use: @sell.rate * @sell.amount) if @sell.order_type == 'limit_sell'
    # try to make orders done
    market_checker(@sell.pair)
  else
    if Order.where(order_status: 'done', pair: params[:order][:pair]).present?
      @currency_price = Sell.where(trading_status: 'done', currency_id: Currency.find_by_slug(params[:sell][:currency_id]).id)
      @currency_price.present? ? @currency_price = @currency_price.last.price : @currency_price = ''
    else
      flash[:danger] = "Unfortunately, there is no trading right now so that we can't show you the chart"
    end
    @pair = params[:order][:pair].to_s
    render :new
  end

  if @buy.save
    flash[:success] = 'your order has successfully submitted.'

    notify_order(@buy.rate, @buy.amount, @buy.order_type)

    @buy.rate.present? ? @buy.update(order_type: 'limit_buy') : @buy.update(order_type: 'market_buy')

    fund = Fund.create_with(amount: 0, crypto_address_id: 1).find_or_create_by(user_id: current_user.id, kind: @buy.pair.split('_').last)
    fund.update(in_use: @buy.rate * @buy.amount) if @buy.order_type == 'limit_buy'

    # try to make orders done
    market_checker(@buy.pair)
  else
    if Order.where(order_status: 'done', pair: params[:order][:pair]).present?
      @currency_price = Sell.where(trading_status: 'done', currency_id: Currency.find_by_slug(params[:sell][:currency_id]).id)
      @currency_price.present? ? @currency_price = @currency_price.last.price : @currency_price = ''
    else
      flash[:danger] = "Unfortunately, there is no trading right now so that we can't show you the chart"
    end
    @pair = params[:order][:pair].to_s
    render :new
  end
end

модель

class Order < ApplicationRecord
  belongs_to :user
  validate :deposited_btc_enough?
  validate :insufficient?
  validates :amount, format: { with: /\A\d+(?:\.\d{0,8})?\z/ }, numericality: { greater_than: 0.000000009, less_than: 100_000_000 }, presence: true
  validate :rate_check
  validates :rate, format: { with: /\A\d+(?:\.\d{0,8})?\z/ }, numericality: { greater_than: 0.000000009, less_than: 100_000_000 }, if: :rate_present?
  validate :checking_order_type

  def rate_present?
    rate.present?
  end

  def checking_order_type
    if order_type == 'sell_limit' || order_type == 'buy_limit'
      errors.add(:Please, 'specify the rate of your order.') unless rate.present?
    end
    if order_type == 'sell_market' || order_type == 'buy_market'
      errors.add(:You, "can't specify the rate of your order.") if rate.present?
    end
  end

  def deposited_btc_enough?
    if rate.present?
      if rate.to_d > '0'.to_d && amount > 0
        deposited_amount = user.fund.amount if user.fund.amount.present?
        amount = rate.to_d * amount.to_s.to_d
        if deposited_amount.present?
          if coin_to_satoshi(amount).to_i > coin_to_satoshi(deposited_amount).to_i
            errors.add(:Your, 'deposited yen is short to order.')
          end
        else
          errors.add(:You, "haven't deposited yen  yet or Your transaction hasn't confirmed yet.")
        end
      else
        errors.add(:You, "can't specify negative numbers here.")
      end
    end
  end

  def to_param
    uuid
  end

  def insufficient?
    if amount.present? && order_type.split('_').last == 'sell'
      if CurrencyUser.find_by(user_id: user.id, currency_id: Pair.find_by(name: pair).currency_id).amount < amount
        errors.add(:amount, 'of this order is more than your holdings.')
        errors[:base] << 'Errors that are related to this order exist.'
      end
    end
  end

  def is_number?(string)
    true if Float(string)
  rescue StandardError
    false
  end

  def rate_check
    if rate.present?
      errors.add(:You, 'can only specify numbers') unless is_number?(rate)
      errors.add(:You, "can't specify the rate as a negative number.") unless '0'.to_d < rate.to_d
    end
  end

конец

форма

 <%= form_for(@sell,remote:true) do |f| %>
          <% if @sell.errors.any? %>
              <div id="error_explanation" class="alert alert-danger">
                <h2><%= @sell.errors.count %>error(s) exist(s).</h2>
                <ul>
                  <% @sell.errors.full_messages.each do |msg| %>
                      <li><%= msg %></li>
                  <% end %>
                </ul>
              </div>
          <% end %>

          <%= f.hidden_field :pair,value:@pair%>

          <%= f.hidden_field :order_type,value:"market_sell"%>

          <p>amount whatever you want to sell like 100</p>
          <div class="input-group">
            <%= f.number_field :amount, class: 'form-control form-group',placeholder:"amount"%>
          </div>
          <%= f.submit 'done', class: "btn btn-large bg-info" %>
      <% end %><br>


     <%= form_for(@buy,remote:true)do |f| %>
        <% if @buy.errors.any? %>
          <div id="error_explanation" class="alert alert-danger">
            <h2><%= @buy.errors.count %>error(s) exist(s).</h2>
            <ul>
              <% @buy.errors.full_messages.each do |msg| %>
                  <li><%= msg %></li>
              <% end %>
            </ul>
          </div>
        <% end %>

Спасибо

1 Ответ

0 голосов
/ 29 апреля 2018

Ваш метод создания имеет слишком большую сложность, и я предполагаю, что вы не написали этот метод с помощью разработки, управляемой тестами, потому что вы бы разбили его на более мелкие методы, если бы имели, вероятно, перенеся больше логики в модель. Я также надеюсь, что ваш стиль кода выглядит не так в реальной жизни. На первый взгляд, я предполагаю, что ваша проблема заключается в следующем:

 def create
   # why are you creating 2 orders??  Can you change this:
   @sell=current_user.orders.build(sell_params)
   @buy=current_user.orders.build(buy_params)

   #to something more like:

   @order = order_from_params
   #...omitting rest of this code because it needs a lot of refactoring.
 end

private 

def order_from_params
  #you should probably only deal with 1 order at a time either buy or sell
  # you must have a field in orders table to indicate buy or sell, probably int?
  if sell_params.present?
    @order = current_user.orders.build(sell_params)
  else
    @order = current_user.orders.build(buy_params)
  end
end

Тогда вам нужно упростить логику в методе создания, поскольку у вас есть только одна модель для работы. Вы не должны полагаться и не делать 2 if @order.save внутри действия создания, поскольку вы снова должны создавать только 1 ордер за раз. Это должно привести вас в правильном направлении. И если вы не будете заниматься тестовой разработкой, у вас будут намного худшие проблемы, чем у вас уже есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...