【问题标题】:how to write a custom validator?如何编写自定义验证器?
【发布时间】:2015-07-20 14:47:13
【问题描述】:

请帮忙解决问题。

型号:

class Video < ActiveRecord::Base
  belongs_to :user

  include ActiveModel::Validations

  class FileSizeValidator < ActiveModel::EachValidator
    def validate_each(record, attribute, value)
      record.errors.add attribute, "must start with 'the'" unless 1 == 1 # this is test
    end
  end

  validates :video, file_size: true
end

class User < ActiveRecord::Base
  devise  :database_authenticatable, 
          :registerable,
          :recoverable, 
          :rememberable, 
          :trackable, 
          :validatable
  has_many :videos
end

表格:

<%= form_for [current_user, @video] do |f| %>
    <%= f.file_field :video %>
    <%= f.submit %>
<% end %>

视频控制器:

def create   
  if params[:video][:video]
    filename = params[:video][:video].original_filename 
  else
    filename = nil
  end

  @video = current_user.videos.create(filename: filename)
  if @video.save
    flash[:success] = :saved
    redirect_to user_videos_path(current_user)
  else
    flash.now[:error] = :not_saved
    render 'new'
  end
end

如果我发送带有“视频”字段的表单,则会收到以下错误消息:

Started POST "/users/48/videos" for 127.0.0.1 at 2015-07-20 17:33:46 +0300
Processing by VideosController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"ukh4iiMQEimDvbOpEtdwTBNeYpdgKZDzepyhnNTWCVRRNx2Xu9v95Wl1iRFp8VDGuDid/BY8ioyedtGbM/imJQ==", "video"=>{"video"=>#<ActionDispatch::Http::UploadedFile:0x007fc278691760 @tempfile=#<Tempfile:/tmp/RackMultipart20150720-25326-1wrjooo.jpg>, @original_filename="im2.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"video[video]\"; filename=\"im2.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "commit"=>"Create Video", "user_id"=>"48"}
  User Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 48]]
   (0.2ms)  BEGIN
   (0.2ms)  ROLLBACK
Completed 500 Internal Server Error in 32ms (ActiveRecord: 1.2ms)

NoMethodError (undefined method `video' for #<Video:0x007fc279389828>):
  app/controllers/videos_controller.rb:25:in `create'

如果我发送带有空字段“视频”的表单,则会收到以下错误消息:

Started POST "/users/48/videos" for 127.0.0.1 at 2015-07-20 17:38:31 +0300
Processing by VideosController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"kLKGzKQiu6QSFC85EQf0xT5bw0LZcHFxlDb6bcsPlTR7zePRPOlUaPjcFYFqIdRPlT08Ka9law5w3IpqLCE6RQ==", "commit"=>"Create Video", "user_id"=>"48"}
Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms)

NoMethodError (undefined method `[]' for nil:NilClass):
  app/controllers/videos_controller.rb:19:in `create'

请帮助编写验证器“file_size”。我使用了文档: http://api.rubyonrails.org/classes/ActiveModel/Validator.html

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4


    【解决方案1】:

    如果你只是想运行一个方法,其实你可以做一些非常简单的事情

    class Video < ActiveRecord::Base
    
      # Notice that it's **validate** without the ending **s**
      validate :video_file_size
    
      # Notice that it doesn't matter what you return, video will stay valid unless you add an error to the `errors` array
      def video_file_size
        if file_size > 10.megabytes
          errors.add :video_file_size, "Video file size must be less than 10 megabytes"
        end
      end
    
    end
    

    这应该足够了,没有额外的验证器类,只有当你打算在多个模型中使用它时才合理。

    【讨论】:

    • 请告诉我如何将上传的文件大小传递给 video_file_size()
    • 嗯,你可以在params找到它!如果您的文件字段名为myfile,您会发现它为params[:myfile].size。迁移您的 Video 模型,添加一列 file_size 并确保在构建对象时传入文件大小。简单有效
    • 参数在模型中不可用:NameError (undefined local variable or method `params' for #<0x007f2054f1f718>
    【解决方案2】:

    如果您的模型上不存在field,则您不能使用validates &lt;field&gt;, ...。如果要加载针对整个模型而不是特定字段运行的验证器,则需要

    class Video < ActiveRecord::Base
    
      validates_with FileSizeValidator
    
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多