根据大小类型定义限制

时间:2013-10-20 21:16:51

标签: ruby-on-rails

好的,我真的非常坚持这个问题,抛出一些想法可能会很好,这可能是一个很长的帖子。

首先让我试着解释一下我要做的事情。目前我有一个名为Book的模型,其中包含一个名为Snippets的嵌套模型。我的Book模型中有一个名为size的列,用于定义它是否为[0 => '短',1 => '中',2 => '长']。我的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的新手,我只是想做到这一点,以便了解代码和你可以做的事情。

我一如既往地感谢您的帮助和反馈。

1 个答案:

答案 0 :(得分: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