4

はじめに

私は、トランザクションのみで構成される非常に単純なレイアウトを持つシステムを実行しています (基本的な CRUD を使用)。各トランザクションには、日付、タイプ、借方金額 (マイナス) および貸方金額 (プラス) があります。オンライン バンキングの明細書を考えてみてください。

私が抱えている問題は、コントローラーをスリムに保ち、データベースに対して過剰なクエリを実行する可能性を心配していることです。

簡単なレポートの例

  • 選択した期間の合計借方SUM(debit) as total_debit
  • 選択した期間の合計クレジット。SUM(credit) as total_credit
  • 全体の合計total_credit - total_debit

  • レポートは動的な日付範囲を許可する必要があります。where(date BETWEEN 'x' and 'y')

  • 日付の範囲は 1 年を超えることはなく、一度に最大で 1000 トランザクション/行に限定されます

だから私が作成するコントローラで:

def report
  @d = Transaction.select("SUM(debit) as total_debit").where("date BETWEEN 'x' AND 'y'")
  @c = Transaction.select("SUM(credit) as total_credit").where("date BETWEEN 'x' AND 'y'")
  @t = @c.credit_total - @d.debit_total
end

追加の質問情報

私の実際のレポートには、6 つまたは 7 つのデータベース クエリがあり (たとえば、type == 1 または type == 2 ごとに総貸方/借方を引き出すなど)、さらに多くの計算があります。たとえば、特定の貸方/借方の種類を合計してから、これらの合計を他の合計から削除します。

「スキニー モデル、ファット コントローラー」を遵守するために最善を尽くしていますが、コントローラーがビューに渡す必要がある変数の量に問題があります。ビューに渡す変数を作成するところまでは、Rails は非常に簡単に見えます。変数を作成する行をコントローラーに入れ、モデルにいくつかのクエリのビットとピースを入れて「スキニー」にする以外に、他にどのようにそれを行うかはわかりません。

モデルで変数を作成し、コントローラーにそれらをビューに渡す場所に欠けているものはありますか?

4

2 に答える 2

4

Activerecord でクエリを記述するより慣用的な方法は、おそらく次のようになります。

class Transaction < ActiveRecord::Base
  def self.within(start_date, end_date)
    where(:date => start_date..end_date)
  end

  def self.total_credit
    sum(:credit)
  end

  def self.total_debit
    sum(:debit)
  end
end

これは、コントローラーで 3 つのクエリを発行することを意味しますが、データベース インデックスを作成し、トランザクション数と時間範囲を適切な量に制限する場合、これは大したことではありません。

@transactions = Transaction.within(start_date, end_date)
@total = @transaction.total_credit - @transaction.total_debit

最後に、Ruby のEnumerable#reduceメソッドを使用して、データベースから取得したトランザクションのリストを直接走査して合計を計算することもできます。

@total = @transactions.reduce(0) { |memo, t|  memo + (t.credit - t.debit) }

非常に小さなデータセットの場合、データベースに 1 回しかヒットしないため、パフォーマンスが向上する可能性があります。ただし、最初のアプローチが望ましいと思います。データベース内のレコード数が増加し始めると、パフォーマンスが確実に向上します。

于 2013-03-17T18:14:35.403 に答える
0

x と y に params[:year_start]/params[:year_end] を入れていますが、安全ですか?

params[:anything]クエリ文字列に直接埋め込まないでください。代わりに、次のフォームを使用してください。

where("date BETWEEN ? AND ?", params[:year_start], params[:year_end])

私の実際のレポートには、おそらく 5 回のデータベース呼び出しがあり、その後、それらの変数に対して 6 回または 7 回の計算が行われます。日付範囲を 1 回クエリしてから、配列/ハッシュなどですべての作業を行う必要がありますか?

これは少し主観的ですが、私の意見を述べます。通常、データベース レイヤーよりもアプリケーション レイヤーをスケーリングする方が簡単です。現在、データベースでパフォーマンスの問題が発生していますか? その場合は、ロジックを Ruby に移行し、アプリケーション サーバーにリソースを追加することを検討してください。そうでない場合、これについて心配するのは時期尚早かもしれません。

作業/計算の大部分をモデルに取り込む方法が本当にわかりません。スコープは理解していますが、どのように日付範囲をスコープに入れて GET パラメータを利用しますか?

has_scopeを見たことがありますか? これは、モデルでスコープを定義し、それらをコントローラー アクションに自動的に適用できる優れた gem です。私は通常、これをフィルタリング/検索に使用しますが、適切な使用例があるようです。

幅広いデータベース呼び出しを介して配列を作成し、その配列に対してさまざまな計算を行い、それらの変数をテンプレートに渡す例を挙げることができれば、すばらしいでしょう。

これは Stack Overflow にはあまり適しておらず、標準的な Rails アプリケーションで行うこととはかけ離れています。Rails ガイドと Ruby の本を読むと、理解するのは難しくありません。

于 2013-03-17T16:42:14.173 に答える