Rails simple-form association not saving - ruby-on-rails

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.

Related

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.

Form accept terms is not validated

I want to archive that the signup form give a validation error if the "accept terms" checkbox is not checked. for some reason the validation messages for all fields appear correctly but not for that checkbox.
users/new.html.erb:
<%= form_for(#user, url: signup_path) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.text_field :name, class: "login", placeholder: :name
...more fields...
<%= f.check_box :agreement, class: "field login-checkbox" %>
<label class="choice" for="Field"><%= t("agree_terms") %></label>
<%= f.submit t("register"), class: "button btn btn-primary btn-large" %>
<% end %>
models/user.rb:
class User < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 50 }
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
# this is the validation
validates :agreement, acceptance: { accept: true }
...
end
Have a look here: http://guides.rubyonrails.org/active_record_validations.html#acceptance
validates :agreement, acceptance: true
should do the trick for you.

Rails adding error to :base not working as expected

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

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

Ruby on Rails - undefined method 'ofertum_path'

I have this model Oferta
class Oferta < ActiveRecord::Base
belongs_to :entidade
has_many :candidatos, :through => :interesses
has_many :interesses, foreign_key: "oferta_id", dependent: :destroy
validates :entidade_id, presence: true
validates :titulo, :presence => { :message => "Título tem de ser preenchido" }, length: { maximum: 40, message: "Título muito extenso! Máximo 40 caracteres!" }
validates :corpo, :presence => { :message => "Corpo tem de ser preenchido" }, length: { maximum: 150, message: "Corpo muito extenso! Máximo 150 caracteres!" }
validates :tipo, inclusion: { in: %w(full_time part_time), message: "%{value} não é válido" }
validates :salario, numericality: { only_integer: true }
i have resources :ofertas in the routes file.
And so far the routing is fine and it works. But in my view:
<% provide(:title,"Editar Oferta") %>
<h1>Editar Oferta</h1>
<div class="row">
<div class="span6 offset3">
<%= simple_form_for #oferta do |f| %>
<%= render 'shared/error_messages' %>
<%= f.input :titulo %>
<%= f.input :corpo %>
<%= f.input :data_inicio %>/<%= f.input :data_fim %>
<%= f.input :atividade %>
<%= f.select :tipo, ["full_time","part_time"], :label => "Tipo" %>
<%= f.input :salario %>
<%= f.select :ativa, ["true","false"], :label => "Atiar/Desativar" %>
<% end %>
</div>
</div>
I get a undefined method 'ofertum_path' in the simple_form_for tag.....
my controller so far is this:
class OfertasController < ApplicationController
def edit
#oferta = Oferta.find(params[:id])
end
I just dont get where the ofertum is coming from. Can someone help me?

Resources