0

わかりました、私は本当にこれに行き詰まっています。いくつかのアイデアを投げかけるのはいいかもしれません.これは長い投稿かもしれません.

まず、私がやろうとしていることを説明してみましょう。現在、Snippets と呼ばれるネストされたモデルを持つ Book と呼ばれるモデルがあります。[0 => 'Short', 1 => 'Medium', 2 => 'Long'] であるかどうかを定義する Book モデルに size という列があります。また、Book コントローラーで総単語数を取得しました。これにより、すべてのスニペットの単語数がわかります。今私が試してみたいことは、サイズ [0,1,2] に応じて、単語数に異なる制限を定義することです。以下に示す例

サイズ (コンテンツの長さの検証) | 文字数

短い (500) 作品ごと | 合計20,000語

作成ごとに中 (700) | 合計50,000語

作成ごとに長い (1000) | 合計100,000語

current_word_count - サイズに応じた total_word_count [短、中、長]

したがって、現在作業している Book で定義されているサイズに応じて、その本のスニペットの単語の合計量を、現在のすべての投稿を含むモデルによって定義したいと思います。たとえば、短い本があり、すでに 10,000 単語がある場合スニペットには 10,000 が残っているはずです。私がこのように考えた理由は、すべてのユーザーが常に必要な最大数を投稿するとは限らないためです。

今コードのために。

まずモデル:

Book.rb

class Book < ActiveRecord::Base
  has_many :snippets
  attr_accessible :title, :book_id, :size


  def get_word_count
    @word_count = 0
    self.snippets.each.do |c|
    @word_count += c.content.scan(/\w+/).size
   end

  def short?
   size == 0
  end

  def medium?
    size == 1
  end

  def long?
    size == 2
  end
end

Snippet.rb

class Snippet < ActiveRecord::Base
  before_create :check_limit
  belongs_to :book
   attr_accessible :content, :book_id 

  validates :book_id, presence: true
  #validates_length_of :content, less_than: 200, if: book.small?
  #validates_length_of :content, less_than: 500, if: book.medium?
  #validates_length_of :content, less_than: 1000, if: book.long?


    def check_limit         
      if book.word_limit_reached?
        errors.add :base, 'Snippet limit reached.'           
        return false
      end       
      return true
    end 
end

これはデータベース アクションであるため、これらのルールを定義するまでは、まだコントローラーに触れる必要はありません。私はここに座ってさまざまなことを試してきましたが、Rails にはまだ慣れていないので、コードと実行できることを理解するためにこれを試してみました。

いつものように、あなたの助けとフィードバックに感謝します。

4

1 に答える 1

0

ああ、カスタム検証の良さ、これは私がすることです:

book.rb

class Book < ActiveRecord::Base
  has_many :snippets


  def get_word_count
    @word_count = []
    self.snippets.each do |c|
      @word_count << c.content.scan(/\w+/).size
    end
    @word_count = @word_count.inject(:+)
    # Similar to what you had before, but this creates an array, and adds each 
    # content size to the array, the inject(:+) is a method done on an array to sum 
    # each element of the array, doesn't work with older versions of ruby, but it's safe
    # 1.9.2 and up
  end

  def short?
    size == 0
  end

  def medium?
    size == 1
  end

  def long?
    size == 2
  end
end

Snippet.rb

class Snippet < ActiveRecord::Base
  belongs_to :book
  validate :size_limit

  # Here I created a constant containing a hash with your book limitation parameters
  # This way you can compare against it easily
  BOOK_SIZE = { 
    0 => {"per" => 500, "total" => 20000},
    1 => {"per" => 700, "total" => 50000},
    2 => {"per" => 1000, "total" => 100000}
  }   


  def  size_limit
    # Sets the book size, which is the same as the hash key for your constant BOOK_SIZE
    book_limit = self.book.size
    # Scans the content attribute and sets the word count
    word_count = self.content.scan(/\w+/).size
    # This is getting the total word count, for all the snippets and the new snippet
    # the user wants to save
    current_snippets_size = (self.book.get_word_count || 0) + word_count
    # This is where your validation magic happens.  There are 2 comparisons done and if they
    # don't both pass, add an error that can be passed back to the controller.  
    # 1st If your content attribute is smaller than allowed for that particular book
    # 2nd If your total snippets content for all previous and current snippet are less than
    # allowed by the total book size defined in the constant
    errors.add(:content, "Content size is too big") unless word_count < BOOK_SIZE[book_limit]['per'] && current_snippets_size < BOOK_SIZE[book_limit]['total']
  end 

end 
于 2013-10-21T00:27:22.443 に答える