stackov8
stackov8

Reputation: 434

Why doesn't this validate the field?

models:

class Video < ActiveRecord::Base
  belongs_to :user

  validates :title, presence: true
end

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

routes:

  devise_for :users

  resources :users do
    resources :videos
  end

  get 'persons/profile', as: 'user_root'

form:

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

video controller:

  def new
    @video = Video.new
  end 

      def create
        p '---------------------'
        p current_user
        p '=================='

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

        video = current_user.videos.create(
                                            title: params[:video][:title], 
                                            filename: filename
        )
        if video.save
          flash[:success] = :post_saved
          redirect_to user_videos_path(current_user)
        else
          flash.now[:error] = :post_not_saved
          render 'new'
        end
      end

      def video_params
        params.require(:video).permit(:title, :video)
      end

If I send the form with the filled field 'title', then the record is added to the database. But if I send the form to the empty field 'title', I get the following error message:

ArgumentError in Videos#create Showing /home/kalinin/rails/vd/app/views/videos/_form.html.erb where line #1 raised: First argument in form cannot contain nil or be empty

The console displays the following:

Started POST "/users/48/videos" for 127.0.0.1 at 2015-07-20 14:48:47 +0300
Processing by VideosController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"QgbvXiEIU33kuz6FE0t3MrQIWyothpbQ0/FUBHCCRC2peYpDucO8sQ5zBD1obVe4H26kQVuTjK83GyQDl6zrXA==", "video"=>{"title"=>""}, "commit"=>"Create Video", "user_id"=>"48"}
"---------------------"
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 48]]
#<User id: 48, email: "[email protected]", encrypted_password: "$2a$10$8h2xqDP8/eShIzfeX5tqJuqisHKiWqDydgpBJiS/xi0...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-07-20 10:55:26", last_sign_in_at: "2015-07-20 10:55:26", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2015-07-20 10:55:25", updated_at: "2015-07-20 10:55:26", status_id: 0, name: "zz", info: nil>
"=================="
   (0.1ms)  BEGIN
   (0.1ms)  COMMIT
   (0.1ms)  BEGIN
   (0.1ms)  ROLLBACK
  Rendered videos/_form.html.erb (1.1ms)
  Rendered videos/new.html.erb within layouts/application (1.5ms)
Completed 500 Internal Server Error in 10ms (ActiveRecord: 0.6ms)

ActionView::Template::Error (First argument in form cannot contain nil or be empty):
    1: <%= form_for [current_user, @video] do |f| %>

Upvotes: 0

Views: 49

Answers (2)

RAJ
RAJ

Reputation: 9747

You have not initialized/defined @video in create action, due to which when error occurs, it tries to render 'new' template and gets @video as nil.

Try updating your create action as follow:

...

@video = current_user.videos.build(
                                    title: video_params[:title], # use your whitelist 
                                    filename: filename
        )

if @video.save

...

Upvotes: 4

Nermin
Nermin

Reputation: 6100

Change your create action

  def create
    p '---------------------'
    p current_user
    p '=================='

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

    @video = current_user.videos.create(
                                        title: params[:video][:title], 
                                        filename: filename
    )
    if @video.save
      flash[:success] = :post_saved
      redirect_to user_videos_path(current_user)
    else
      flash.now[:error] = :post_not_saved
      render 'new'
    end
  end

Wherever you got video change to @video

Upvotes: 1

Related Questions