Rails adding error to :base not working as expected - ruby-on-rails

I have a double nested form:
<%= simple_form_for #item, html: { class: "create-item-form" } do |item_builder| %>
<div class="well">
<%= item_builder.input :name, required: false, error: false, label: "item name" %>
<%= item_builder.input :description, as: :text, required: false, error: false, label: "How do users earn this item?" %>
<%= item_builder.input :tag_list, required: false, label: "Tags (these will help users find your item)" %>
<%= item_builder.simple_fields_for :user_items do |user_item_builder| %>
<%= user_item_builder.input :foo, as: :hidden, input_html: { value: "bar" } %>
<%= user_item_builder.simple_fields_for :user_item_images do |user_item_images_builder| %>
<%= user_item_images_builder.input :foo, as: :hidden, input_html: { value: "bar" } %>
<%= user_item_images_builder.input :picture, as: :file, required: false,
error: false, label: "Pictures of you earning this item",
input_html: { multiple: true,
name: "item[user_items_attributes][0][user_item_images_attributes][][picture]" } %>
<% end %>
<% end %>
</div>
<div class="clearfix">
<%= item_builder.submit 'Submit new item request', class: "btn btn-primary pull-right inherit-width" %>
</div>
<% end %>
When a user doesn't upload a file for the user_item_image I need to display an error message. I wrote a custom validation:
user_item_image.rb
class UserItemImage < ActiveRecord::Base
include PicturesHelper
attr_accessor :foo
mount_uploader :picture, PictureUploader
belongs_to :user_item
validate :picture_size
validate :has_picture
private
def has_picture
errors.add(:base, 'You must include at least one picture.') if picture.blank?
end
end
But I get the error message:
User items user item images base You must include at least one picture.
How can I rewrite the validation so that it doesn't show the attribute and only shows the message.

Why not use
validates :picture, presence: true
on your useritem model

Related

How to dynamically set 'name' attribute of a simple form input

I am using Simple Form in a Rails application in which a FormsController controller was defined as follow :
class FormsController < ApplicationController
def index
#forms = Form.all
end
def new
#form = Form.new(form_params)
end
...
private
def form_params
params.require(:form).permit(:user, :name, :tag, :link, :repo)
end
end
A new view is used to get some inputs from user
<div class="form">
<%= simple_form_for #param do |f| %>
<div class="form-inputs";>
<%= f.input :user %>
<%= f.input :name %>
<%= f.input :tag %>
<%= f.input :link %>
<%= f.input :repo %>
</div>
<div class="form-actions">
<%= f.button :submit, "Create", class: "btn-primary" %>
</div>
<% end %>
</div>
I checked what's the generated name for a each field using inspect :
<input type="text" name="form[user]" id="form_user">
Printing parameters in controller while submitting a form returns :
{“user”=>”value1”, “name”=>”value2”, “tag”=>”value3”, “link”=>”value4”, “repo”=>”value5”}
From now, I would like to duplicate that's simple form few times. So, I first updated the field name from form[<parameter>] to form[1][<parameter>]
<div class="form-inputs";>
<%= f.input :user, input_html: { name: 'form[1][user]' } %>
<%= f.input :name, input_html: { name: 'form[1][name]' } %>
<%= f.input :tag, input_html: { name: 'form[1][tag]' } %>
<%= f.input :link, input_html: { name: 'form[1][link]' } %>
<%= f.input :repo, input_html: { name: 'form[1][repo]' } %>
</div>
What I get from now as parameters output is :
"form"=>{"1"=>{"“user”"=>"value1", "“name”"=>"value2", "“tag”"=>"value3", "“link”"=>"value4", "“repo”"=>"value5"}}
What's the best way to dynamically allocate the id to the form[<id>][user] to the field ?
Is it possible to get parameters formatted as follow ?
form => { 1 => {user: "user1" }, 2 => {user: "user2" }, 3 => {user: "user3" }.. }
form => { 1 => {name: "name1" }, 2 => {name: "name2" }, 3 => {name: "name3" }.. }
...

Simple_form_for on Rails - how to show error validations after submit

I'm trying to only show errors in my form when the user clicks the submit button but currently, it is displaying all errors before the user clicks the submit button. How do I only show errors when the user submits the form?
I'm using simple-form in Rails
Here is my simple-form:
<div class="col-md-10 col-lg-8 col-xl-5 col-md-offset-4 mx-auto">
<%= simple_form_for #customer, url: customers_path, method: :post do |f| %>
<%= f.error_notification %>
<%= f.input :first_name %>
<%= f.input :last_name %>
<%= f.input :email, input_html: { autocomplete: 'email' } %>
<%= f.input :budget, collection: ["€200,000 - €299,999", "€300,000 - €399,999", "€400,000 - €499,999", "€500,000 - €649,999", "€650,000 - €799,999", "€800,000 - €1,000,000", "€1,000,000 +"] %>
<%= f.input :comments, :as => :text, :input_html => { 'rows' => 10, 'cols' => 10 } %>
<%= f.button :submit, "Submit", class: "btn-primary trigger mt-1" %>
<% end %>
</div>
Here are my customer validations in my customer model:
class Customer < ApplicationRecord
validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }, uniqueness: true
validates :first_name, presence: true, length: { minimum: 2 }
validates :last_name, presence: true, length: { minimum: 2 }
validates :budget, presence: true
validates :comments, presence: true
end
Thank you
you can change simple_form_for (line 2) like this below
<%= simple_form_for #customer, html: { novalidate: true }, url: customers_path, method: :post do |f| %>
explanation:
by adding , html: { novalidate: true } This option adds a new novalidate property to the form, instructing it to skip all HTML 5 validation.

Rails simple-form association not saving

Am new to RoR and Simple_form. I have a simple set-up where I have an association between 2 classes. The form I use is not updating/saving and always setting the value back to blank. Looked at the docs and other postings, what am I doing wrong?
Classes
class Annotation < ApplicationRecord
has_many :comments, dependent: :destroy
belongs_to :documenttype
has_attached_file :file, styles: { large: "600x600>", medium: "500x500>", thumb: "150x150#" }, default_url: "/images/:style/missing.png"
accepts_nested_attributes_for :documenttype
validates_attachment_content_type :file, content_type: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf']
validates :name, presence: true, uniqueness: true, length: { minimum: 10, maximum: 50 }
validates :description, length: { minimum: 20, maximum: 500 }
validates :documenttype, presence: true
validates :file, presence: true
end
class Documenttype < ApplicationRecord
has_many :annotations
validates :name, presence: true, uniqueness: true, length: { minimum: 5 }
end
Params
def annotation_params
params.require(:annotation).permit(:name, :description, :file, :active, :documenttype)
end
def documenttype_params
params.require(:documenttype).permit(:name, :description, :active, annotation_attributes: [:id, :name])
end
This is the form...
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<%= simple_form_for #annotation, html: { class: 'form-horizontal', multipart: true },
wrapper: :horizontal_form,
wrapper_mappings: {
check_boxes: :horizontal_radio_and_checkboxes,
radio_buttons: :horizontal_radio_and_checkboxes,
file: :horizontal_file_input,
boolean: :horizontal_boolean
} do |f| %>
<%= f.error_notification %>
<%= f.input :name, placeholder: 'Enter name' %>
<%= f.input :description, placeholder: 'Description' %>
<%= f.association :documenttype %>
<%= f.input :active, as: :boolean %>
<% if #annotation.file.blank? %>
<%= f.input :file, as: :file %>
<% else %>
<% end %>
<%= f.button :submit %>
<% unless #annotation.file.blank? %>
<%= link_to ' Annotate', annotations_path, :class => "btn btn-default" %>
<% end -%>
<% end %>
<p><br><%= link_to 'List' , annotations_path %></p>
</div>
<div class="col-md-6">
<% unless #annotation.file.blank? %>
<%= image_tag #annotation.file.url(:large) %>
<% end %>
</div>
</div>
I found the solution; I needed to add :documenttype_id to annotation_params.

Rails 4.1 Carrierwave not uploading images

I am using the carrierwave gem to upload images of movie listings. I have created a migration creating a image column to my listings database.
updated the Listing model.rb file
class Listing < ActiveRecord::Base
mount_uploader :image, ImageUploader
belongs_to :user
end
added the :html = > { multipart: true } command to my simple form
<div class="wizard-container">
<%= simple_form_for(#listing, url: new_user_registration_path, method: :get, :html => { multipart: true } ) do |f| %>
<div class="card wizard-card ct-wizard-orange" id="wizard">
<!-- You can switch "ct-wizard-orange" with one of the next bright colors: "ct-wizard-blue", "ct-wizard-green", "ct-wizard-orange", "ct-wizard-red" -->
<div class="wizard-header">
<h3>
<b>LIST</b> YOUR MOVIE <br>
<small>This information will let us know more about your movie</small>
</h3>
</div>
And the image field to my listing.html.erb file
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<%= f.file_field :image %><br>
</div>
</div>
but when i create a listing the folloeing information , appears in console
Started GET "/users/sign_up?utf8=%E2%9C%93&listing%5Btitle%5D=Top+Gun&listing%5Btime%5D=14.35&listing%5Bdate%5D=24%2F03%2F2016&listing%5Bseats%5D=5&listing%5Bvenue_name%5D=Preston+Library&listing%5Bimage%5D=IMG_0892.JPG&listing%5Bprice%5D=2.3&listing%5Blocation%5D=Preston+Town+Hall&listing%5Bother_info%5D=This+is+a+great+venue&listing%5Bprojector%5D=0&listing%5Bcables%5D=0&listing%5Blaptops%5D=0&listing%5Bseating%5D=0&listing%5Bblinds%5D=0&listing%5Binternet%5D=0&listing%5Blighting%5D=0&listing%5Bcamcorder%5D=0&listing%5Bcatering%5D=0&listing%5Btoilets%5D=0&listing%5Bfire%5D=0&listing%5Bfire%5D=1&commit=Create+Listing" for 127.0.0.1 at 2015-03-24 14:36:31 +0000
Processing by Devise::RegistrationsController#new as HTML
Parameters: {"utf8"=>"✓", "listing"=>{"title"=>"Top Gun", "time"=>"14.35", "date"=>"24/03/2016", "seats"=>"5", "venue_name"=>"Preston Library", **"image"=>"IMG_0892.JPG",** "price"=>"2.3", "location"=>"Preston Town Hall", "other_info"=>"This is a great venue", "projector"=>"0", "cables"=>"0", "laptops"=>"0", "seating"=>"0", "blinds"=>"0", "internet"=>"0", "lighting"=>"0", "camcorder"=>"0", "catering"=>"0", "toilets"=>"0", "fire"=>"1"}, "commit"=>"Create Listing"}
So it captures the image but does mot display the image?
this app is slightly different to what i normally do , I make the user sign in first and then create details ,this app you create listings and then create an account
new.html.erb
<%= render 'layouts/header' %>
<h2 class="text-center">Sign up</h2>
<%
if !user_signed_in?
resource.listings.build
resource.listings[0].title = params[:listing][:title]
resource.listings[0].time = params[:listing][:time]
resource.listings[0].date = params[:listing][:date]
resource.listings[0].seats = params[:listing][:seats]
resource.listings[0].venue_name = params[:listing][:venue_name]
resource.listings[0].location = params[:listing][:location]
resource.listings[0].other_info = params[:listing][:other_info]
resource.listings[0].price = params[:listing][:price]
resource.listings[0].projector = params[:listing][:projector]
resource.listings[0].cables = params[:listing][:cables]
resource.listings[0].laptops = params[:listing][:laptops]
resource.listings[0].seating = params[:listing][:seating]
resource.listings[0].blinds = params[:listing][:blinds]
resource.listings[0].lighting = params[:listing][:lighting]
resource.listings[0].camcorder = params[:listing][:camcorder]
resource.listings[0].catering = params[:listing][:catering]
resource.listings[0].toilets = params[:listing][:toilets]
resource.listings[0].fire = params[:listing][:fire]
resource.listings[0].internet = params[:listing][:internet]
end
%>
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: {class: "form-signin"}) do |f| %>
<%= f.error_notification %>
<%= f.input :name, required: true, autofocus: true, label: false, placeholder: "Name", input_html: {class: "form-control"} %>
<%= f.input :email, required: true, label: false, placeholder: "Email", input_html: {class: "form-control"} %>
<%= f.input :password, required: true, label: false, placeholder: "Password", input_html: {class: "form-control"} %>
<%= f.input :password_confirmation, required: true, label: false, placeholder: "Password Confirmation", input_html: {class: "form-control"} %>
<div style="display:none">
<%= f.fields_for :listings do |listing_form| %>
<%= listing_form.input :title, label: false, placeholder: "Movie Title", input_html: {class: "form-control"} %>
<%= listing_form.input :time, label: false, placeholder: "What time does your movie start?", input_html: {class: "form-control"} %>
<%= listing_form.input :date, label: false, placeholder: "What date", input_html: {class: "form-control"} %>
<%= listing_form.input :seats, label: false, placeholder: "Number of seats", input_html: {class: "form-control"} %>
<%= listing_form.input :venue_name, label: false, placeholder: "Name of venue", input_html: {class: "form-control"} %>
<%= listing_form.input :location, label: false, placeholder: "Address", input_html: {class: "form-control", rows: 5 } %>
<%= listing_form.input :other_info, label: false, placeholder: "Other information", input_html: {class: "form-control", rows: 5} %>
<%= listing_form.input :price, label: false, placeholder: "Ticket Price (£)", input_html: {class: "form-control"} %>
<p> Projector </p>
<%= listing_form.input :projector, required: false, label: false %>
<p> Cable </p>
<%= listing_form.input :cables, required: false, label: false %>
<p> Laptop </p>
<%= listing_form.input :laptops, required: false, label: false %>
<p> Seating </p>
<%= listing_form.input :seating, required: false, label: false %>
<p> Blinds </p>
<%= listing_form.input :blinds, required: false, label: false %>
<p> Lighting </p>
<%= listing_form.input :lighting, required: false, label: false %>
<p> Camcorder </p>
<%= listing_form.input :camcorder, required: false, label: false %>
<p> Catering </p>
<%= listing_form.input :catering, required: false, label: false %>
<p> Toilets </p>
<%= listing_form.input :toilets, required: false, label: false %>
<p> Fire alarm </p>
<%= listing_form.input :fire, required: false, label: false %>
<p> Wifi/internet </p>
<%= listing_form.input :internet, required: false, label: false %>
<% end %>
</div>
<%= f.button :submit, "Sign up", class: "btn btn-primary btn-block" %>
<%= render "devise/shared/links" %>
<% end %>
application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(
:name,
:email, :password, :confirmation_password,
listings_attributes: [
:title, :time, :date, :seats,
:venue_name, :location, :other_info,
:price, :projector, :cables,
:laptops, :seating, :blinds,
:lighting, :camcorder, :catering,
:toilets, :fire, :internet, :image
]
)
end
devise_parameter_sanitizer.for(:account_update) << :name
end
end
any thoughts
Neil
rake routes
Rails.application.routes.draw do
resources :listings
devise_for :users
root 'pages#home'
get 'about' => 'pages#about'
get 'pages/contact'
get 'dashboard' => 'pages#dashboard'
get 'start' => 'listings#listing'

How do I filter posts with Ruby-on-Rails

I have a job listing project set up and I want to be able to filter by several filters. I want to be able to have sidebar which can filter by certain elements - :city, :jobtype, and :contracttype
Is there a straightforward way to create radio buttons that will display the options available to the user i.e for :city a list of London, Manchester, Brighton etc which can be ticked to display those specific jobs?
I'm new to rails so having a hard time working out what I need to do, if anyone could explain what I need to do I'd really appreciate it!
My code is as follows:
index.html.erb -
<% #jobs.each do |job| %>
<div class="job">
<h2><%= job.position %></h2>
<p>Company: <%= job.company %></p>
<p>Salary: <%= job.salary %></p>
<p>Website: <%= job.companywebsite %></p>
<p>Twitter: <%= job.companytwitter %></p>
<p>Contract Type: <%= job.contract %></p>
<p>City: <%= job.city %></p>
<p>Expiry date: <%= job.expirydate %></p>
<p>Job Type: <%= job.jobtype %></p>
<p>Full Description:<br><br><%= job.description %></p>
<p>How to apply: <%= job.apply %></p>
</div>
<% end %>
job.rb -
class Job < ActiveRecord::Base
validates :position, presence: true
validates :company, presence: true
validates :salary, presence: true
validates :companywebsite, presence: true
validates :companytwitter, presence: true
validates :contract, presence: true
validates :city, presence: true
validates :expirydate, presence: true
validates :jobtype, presence: true
validates :description, presence: true
validates :apply, presence: true
end
jobs_controller.erb -
class JobsController < ApplicationController
def index
#jobs = Job.page(params[:page]).per(25)
end
def new
#job = Job.new
end
def create
#job = Job.new(params.require(:job).permit(:position, :company, :salary, :companywebsite, :companytwitter, :contract, :city, :expirydate, :jobtype, :description, :apply ))
if #job.save
redirect_to root_path
else
render "new"
end
end
end
new.html.erb -
<%= simple_form_for #job, html: { multipart: true } do |form| %>
<%= form.input :position, input_html: { maxlength: 60 }, placeholder: "Job Position", label: false %>
<%= form.input :company, input_html: { maxlength: 60 }, placeholder: "Company name", label: false %>
<%= form.input :salary, input_html: { maxlength: 60 }, placeholder: "Salary", label: false %>
<%= form.input :companywebsite, input_html: { maxlength: 60 }, placeholder: "Company Website", label: false %>
<%= form.input :companytwitter, input_html: { maxlength: 60 }, placeholder: "Twitter Handle e.g #Hatch_Inc", label: false %>
<%= form.input :contract, input_html: { maxlength: 60 }, placeholder: "Contract Type", label: false %>
<%= form.input :city, input_html: { maxlength: 60 }, placeholder: "City", label: false %>
<%= form.input :expirydate, input_html: { maxlength: 60 }, placeholder: "Expiry date", label: false %>
<%= form.input :jobtype, input_html: { maxlength: 60 }, placeholder: "Job Type", label: false %>
<%= form.input :description, input_html: { maxlength: 60 }, placeholder: "Full job description", label: false %>
<%= form.input :apply, input_html: { maxlength: 60 }, placeholder: "How to apply", label: false %>
<%= form.button :submit %>
<% end %>
Here's an example that uses JQuery to submit an AJAX request (so your page doesn't refresh every time a box is checked). In your view, you create a checkbox for each unique country. Jquery parameterizes the selected countries and submits them to your controller (specifying that you want to respond with JavaScript). A scope in your Jobs model applies the filter.
index.html.erb
<div id='job-list'>
<% #jobs.each do |job| %>
<div class="job">
<!-- Display your job here -->
</div>
<% end %>
</div>
<div id='countries'>
<h4> Country Filter: </h4>
<% #countries= Job.uniq.pluck(:country) %>
<% #countries.each do |c| %>
<br><input id="<%= c %>" type="checkbox" class="country-select" checked><label for="<%= c %>"> <%= c %> </label>
<% end %>
</div>
index.js.erb
var jobs = $('#job-list');
jobs.empty();
<% #jobs.each do |job|%>
jobs.append("<div class='job'><%= job %></div>"); // job display goes here
<% end %>
courses.coffee
getParams = ->
params = ""
countries = []
$(".country-select:checked").each ->
countries.push($(this).attr('id'))
params += "&#{$.param({countries: countries})}";
return params
$('.country-select').on 'change', (event) =>
$.ajax "/jobs.js?"+getParams(),
type: 'GET'
dataType: 'script'
Jobs controller
class JobsController < ApplicationController
respond_to :html, :js
def index
#jobs = Job.page(params[:page]).per(25).by_country(params[:countries])
end
end
Job model
class Job < ActiveRecord::Base
scope :by_country, -> (countries) { where(:country => (countries|| Course.uniq.pluck(:country)) ) }
end

Resources