After following Michael Hartl's Rails Tutorial I moved the 'micropost feed' from /
to /members
, and now when I submit a post that doesn't validate properly (too many characters, missing content etc.) rails returns an error saying:
ArgumentError in MicropostsController#create First argument in form cannot contain nil or be empty
The related interface test error returns:
FAIL["test_micropost_interface", MicropostsInterfaceTest, 2015-06-22 11:13:28 +0800]
test_micropost_interface#MicropostsInterfaceTest (1434942808.57s)
Expected at least 1 element matching "div#error_explanation", found 0..
Expected 0 to be >= 1.
test/integration/microposts_interface_test.rb:19:in `block in <class:MicropostsInterfaceTest>'
How can I fix these errors so user friendly error messages (div#error_explanation
) will display correctly?
Supporting info
MembersController:
class MembersController < ApplicationController
before_filter :logged_in_user
def index
@micropost = current_user.microposts.build
@feed_items = current_user.feed.paginate(page: params[:page])
end
end
MicropostsController:
class MicropostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
@micropost = current_user.microposts.build(micropost_params)
if @micropost.save
flash[:success] = "Micropost created!"
# redirect_to root_url
redirect_to members_path
else
@feed_items = []
@micropost = []
render 'members/index'
end
end
def destroy
@micropost.destroy
flash[:success] = "Micropost deleted"
# redirect_to request.referrer || root_url
redirect_to request.referrer || members_path
end
private
def micropost_params
params.require(:micropost).permit(:content, :picture)
end
def correct_user
@micropost = current_user.microposts.find_by(id: params[:id])
# redirect_to root_url if @micropost.nil?
redirect_to members_path if @micropost.nil?
end
end
_micropost_form.html.erb
<%= form_for(@micropost, html: { multipart: true }) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost (420 chars max)..." %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<span class="picture">
<%= f.file_field :picture, accept: 'image/jpeg,image/gif,image/png' %>
</span>
<% end %>
<script type="text/javascript">
$('#micropost_picture').bind('change', function() {
size_in_megabytes = this.files[0].size/1024/1024;
if (size_in_megabytes > 5) {
alert('Maximum file size is 5MB. Please choose a smaller file.');
}
});
</script>
app/models/micropost.rb
class Micropost < ActiveRecord::Base
belongs_to :user
default_scope -> { order(created_at: :desc) }
mount_uploader :picture, PictureUploader
validates :user_id, presence: true
validates :content, presence: true, length: { maximum: 420 }
validate :picture_size
private
# Validates the size of an uploaded picture.
def picture_size
if picture.size > 5.megabytes
errors.add(:picture, "should be less than 5MB")
end
end
end
Update
_error_messages.html.erb
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>