2015-07-20 3 views
0

, пожалуйста, помогите решить проблему.Как написать пользовательский валидатор?

модели:

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 "https://stackoverflow.com/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 "https://stackoverflow.com/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

ответ

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 

Этого должно быть достаточно, без дополнительного класса валидатора, что разумно, только если вы собираетесь использовать его в нескольких моделях.

+0

скажите, пожалуйста, как передать размер загруженного файла в video_file_size() – stackov8

+0

Ну, вы можете найти его в 'params'! Если ваше поле файла называется 'myfile', вы найдете его как' params [: myfile] .size'. Перенесите свою модель «Видео», добавив столбец «file_size» и убедитесь, что вы передаете размер файла при создании объекта. Простой и эффективный –

+0

params, к сожалению, недоступно в модели: NameError (неопределенная локальная переменная или метод 'params 'для # ): – stackov8

0

Вы не можете использовать validates <field>, ... если field не существует на вашей модели. Если вы хотите загрузить валидатор, который работает против всей модели, а не конкретной области, необходимо

class Video < ActiveRecord::Base 

    validates_with FileSizeValidator 

end