本を注文するための Ruby モデル スコープを作成する方法はありますか? (数字もアルファベットもなし)
概要
私は、本からの引用と、その引用についてのメモや感想を掲載するアプリを持っています。本の順序、章の順序、ページの順序の順に引用をリストしたいと思います。
ActiveRelation を維持するために、これをモデル内のスコープに移動する方法はありますか?
のように
class Quote
scope :sorted, ->(order_of_books|book|) { where("reference_book = ?", book) }
end
私のコントローラーには、書籍の注文ごとに引用を並べ替える次のようなコードがあります。
# /app/controllers/quotes_controller.rb
def quotes
@quotes = Quotes.all
@sorted_quotes = []
order_of_books.each do |book|
@temp_array = []
if @quotes.any? { |quote| quote[:reference_book] == book}
@temp_array << @quotes.detect { |quote| quote[:reference_book] == book}
# @temp_array.sort_by! { |quote| quote.reference_paragraph, quote.reference_sentence }
@sorted_quotes << @temp_array
end
end
end
# /app/models/concerns/book_concern.rb
def order_of_books
[
"Book A",
"Book B",
"Book C",
]
end
参考用のデータベーステーブルです。
# db/schema.rb
create_table "quotes", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "text", null: false
t.string "reference_book", null: false
t.integer "reference_chapter", null: false
t.integer "reference_paragraph", null: false
t.integer "reference_sentence", null: false
t.string "image"
t.text "notes"
end
エラー
問題は、引用符を並べ替えようとしていることであり、ビュー内で quote.image のようなものを呼び出そうとすると、他のすべてのコードが壊れて、次のエラーが発生します。
問題は、引用符を並べ替えようとしていることであり、ビュー内で quote.image のようなものを呼び出そうとすると、他のすべてのコードが壊れて、次のエラーが発生します。
サイドノート
コントローラー内のsort_by!を実行しようとしている行です。段落と文が機能しないので、コメントアウトしました。今のところ、それは私にとってそれほど重要ではありません。
コントローラー内のsort_by!を実行しようとしている行です。段落と文が機能しないので、コメントアウトしました。今のところ、それは私にとってそれほど重要ではありません。
解決策
書籍ごとに複数の引用があると仮定すると (コードに新しい行を追加せずに、時間の経過とともにさらに書籍を追加することになります)、書籍テーブルを用意し、書籍の並べ替えフィールドを保存することで、データをもう少し適切に正規化することができます。本の好ましい並べ替え順序を取得するため (コードに直接組み込まれるのではなく)。
# models/book.rb
class Book < ApplicationRecord
validates :sort, presence: true
end
# models/quote.rb
class Quote < ApplicationRecord
belongs_to :book
end
# db/schema.rb
create_table "books", force: :cascade do |t|
t.string "title", null: false
t.string "author"
t.integer "sort", null: false
end
create_table "quotes", force: :cascade do |t|
t.string "text", null: false
t.bigint "book_id", null: false # < new column
t.integer "reference_chapter", null: false
t.integer "reference_paragraph", null: false
t.integer "reference_sentence", null: false
t.string "image"
t.text "notes"
# TODO: you will also want a foreign key constraint here for quote.book_id
end
次に、このリレーションシップを使用して引用を並べ替え、複数の列を order メソッドに渡します。つまり、最初に book.sort で並べ替え、次に、reference_chapter (同じ書籍内のすべての引用について)、次に、reference_paragraph (同じ章内のすべての引用について) で並べ替えることができます。ベストプラクティスとして、同じ本+章+段落+文から複数の引用があった場合に備えて、最終的な曖昧さ回避として quotes.id を使用することをお勧めします。
# models/quote.rb
class Quote < ApplicationRecord
scope :sorted, -> { joins(:book).order('books.sort ASC, reference_chapter ASC, reference_paragraph ASC, reference_sentence ASC, id ASC') }
end