I am using Paperclip to show screenshots of apps. It’s on a model called screenshots
which belongs_to: :app
and has an image attribute for the attachment.
I want the App model to validate that there is at least one screenshot before it gets saved, which seems to be working with: validates :screenshots, presence: true
I get the proper Screenshots can’t be blank in @app.errors.full_messages
when I try to submit without one.
However, using simpleform (or vanilla rails), I get no error message displaying around the field it self unlike all the other fields. I’ve tried a few things like moving the validation around to the screenshot model and using validates_associated
on the app model. Nothing seems to work.
So, my question is A) am I validating correctly and B) how can I get my validation errors to show up on the form?
Hi @edwardloveall, are you displaying the errors in the form with something like:
<% if @post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% @post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
And creating a styling hook around the form fields:
<div class="field_with_errors">
<input id="post_title" name="post[title]" size="30" type="text" value="">
</div>
I’m asking because I tend to forget this 
edit: both the code samples are from the Rails Guides
Mostly, yes. I was using a partial that did basically what you showed for errors, but simpleform actually has a helper:
<%= f.error_messages %>
And then each error message is displayed inline in the html:
<div class="field_with_errors">
<label for="post_title">Title</label>
<input id="post_title" name="post[title]" type="text">
<span class="error">can't be blank</span>
</div>
More or less that, but I’ve simplified it.
Well, in that case the only thing I can think of checking is that the class “field_with_errors” does have styles applied in the css. Wish I could help more 
Yeah, it doesn’t show up, which is mostly the problem. Simpleform knows that it’s a required field, rails triggers the validation, I just get no field wrapping.
Thanks though!
Which method are you using in your controller to save the form, “save” or “save!” ?
Just save
def create
@app = App.new(params[:app])
if @app.save
redirect_to admin_apps_path
else
@app.screenshots.build
render 'new'
end
end
I think the problem might be with the placement of your “@app.screenshots.build” in the ‘negative’ branch of the method. If the association is properly set and validated you shouldn’t need to explicitly build the association object, Rails should pick up that App “has screenshots” and save both objects correctly.
I’ll try that @pedromoreira! I’m currently working on a different branch and should finish that before I come back to this, but I’ll let you know how it goes.
I tried this, but what happens is when I have a validation error, the app displays the form without the screenshot field, so there’s not even a field to put an error on to.
Can you post the full code for the controller, model and form?
Sure
apps_controller.rb
class Admin::AppsController < AdminController
def index
@apps = App.all
end
def new
@app = App.new
@app.screenshots.build
end
def create
@app = App.new(params[:app])
if @app.save
redirect_to admin_apps_path
else
@app.screenshots.build
render 'new'
end
end
def edit
@app = find_app
end
def update
@app = find_app
if @app.update_attributes(params[:app])
redirect_to admin_apps_path
else
render 'edit'
end
end
def destroy
@app = find_app
@app.destroy
redirect_to admin_apps_path
end
private
def find_app
@app = App.find(params[:id])
end
end
app.rb
class App < ActiveRecord::Base
attr_accessible :name, :website, :description, :ios_url, :android_url, :icon, :screenshots_attributes
has_many :screenshots
has_attached_file :icon
accepts_nested_attributes_for :screenshots, allow_destroy: true
validates :name, presence: true
validates :ios_url, presence: true, unless: :android_url?
validates :android_url, presence: true, unless: :ios_url?
validates :description, presence: true
validates :icon, presence: true
validates :screenshots, presence: true
end
screenshot.rb
class Screenshot < ActiveRecord::Base
belongs_to :app
attr_accessible :image
has_attached_file :image
end
_form.html.erb (rendered for new and edit in apps)
<%= simple_form_for [:admin, @app], html: { multipart: true } do |form| %>
<h1><%= form_title(form) %></h1>
<%= form.input :name %>
<%= form.input :website %>
<%= form.input :ios_url, label: "iOS Download Link" %>
<%= form.input :android_url, label: "Android Download Link" %>
<%= form.input :description %>
<%= form.input :icon %>
<%= form.simple_fields_for :screenshots do |screenshot_fields| %>
<%= label_tag nil, "Screenshots" %>
<%= render 'screenshot_fields', form: screenshot_fields %>
<% end %>
<div class="input">
<%= link_to_add_fields("Add Screenshot", form, :screenshots) %>
</div>
<%= form.button :submit %>
<% end %>
_screenshot_fields.html.erb
<% if form.object.new_record? %>
<%= form.input :image, label: false %>
<% else %>
<%= image_tag form.object.image.url %>
<%= form.hidden_field :_destroy %>
<%= link_to "Delete Screenshot", "#", class: "js-remove-fields remove-fields" %>
<% end %>
I wanted to try this for myself to see if I could help any further, but I didn’t find the time.
While searching around trying to understand the problem I’ve found that, by using ‘accepts_nested_attributes_for’, you might get the ‘Screenshots can’t be blank’ error in ‘@app.errors.full_message’, but it might not be able to identify the proper field to highlight in the form. There is a open issue in the rails repo that might offer further information.
Also, this seems to have a lot of ‘moving parts’ and it would probably be best to try and find a simpler solution.
Anyway, hope this helps!
So, I did eventually fix this, with Chad’s help. The validation is working fine, but the problem is the actual attribute (:image
) isn’t being validated. It’s :screenshot
. So simple_form doesn’t have any idea where to put the error. So, I used an if statement in my view
<% if @app.errors[:screenshots].present? %>
to check for errors, and then display something accordingly. Not the cleanest, but it works.