好的,我真的非常坚持这个问题,抛出一些想法可能会很好,这可能是一个很长的帖子。
首先让我试着解释一下我要做的事情。目前我有一个名为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的新手,我只是想做到这一点,以便了解代码和你可以做的事情。
我一如既往地感谢您的帮助和反馈。
答案 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