Associated models not passing validation errors to parent - ruby-on-rails

I am currently building a Rails App and I have two associated models.
Subnets and devices, the devices are inside the subnets. Both do some degree of validation.
class Subnet < ApplicationRecord
has_many :devices , dependent: :destroy
validates_presence_of :devices
validates :name, presence: true, uniqueness: true
validates :CIDR, presence: true
validates_associated :devices
end
class Device < ApplicationRecord
belongs_to :subnet
validates :subnet, :presence => true
validates :name, presence: true, uniqueness: {scope: :subnet_id}
validates :IP, presence: true, uniqueness: {scope: :subnet_id}
end
When trying to create a new device, which already exists, this new device will not be created - which is supposed to work like that.
Although, I would like some kind of error message displayed after this incident, but my code doesn't seem to hand over the errors from child to parent.
The relevant part of my view for the subnets (which also contains the error handling) looks like this:
...
<% if #subnet.errors.any? %> <-------- This line seems to not get the information about the failed validation of the device
<div id="error_explanation">
<h2>
<%= pluralize(#subnet.errors.count, "error") %> prohibited
this subnet from being saved:
</h2>
<ul>
<% #subnet.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<h2>Add a device:</h2>
<%= form_with(model: [ #subnet, #subnet.devices.build ], local: true) do |form| %>
<p>
<%= form.label :name %><br>
<%= form.text_field :name %>
</p>
<p>
<%= form.label :IP %><br>
<%= form.text_field :IP %>
</p>
<p>
<%= form.label :notes %><br>
<%= form.text_area :notes %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
...
And the create function for the devices from the device_controller looks like this:
def create
#subnet = Subnet.find(params[:subnet_id])
#device = #subnet.devices.create(device_params)
redirect_to subnet_path(#subnet)
end
How can I get my subnet show view to react to the errors from the devices?

Related

accepts_nested_attributes_for with validations and using find_or_create_by

I have a user model and a town model. A user belongs_to a town:
# models/user.rb
class User < ApplicationRecord
belongs_to :town
accepts_nested_attributes_for :town
validates :last_name, presence: true
end
# models/town.rb
class Town < ApplicationRecord
has_many :users
validates :name, presence: true
validates :name, uniqueness: true
end
You go to create a new user record: there is a text_box in order to put in the associated town's name. When submitted, the rails application should do the following:
use find_or_create_by. go and check if there already exists a town record with the name attribute passed in.
If a town record DOES exist with that given name attribute, just associate that existing town record to this new user record
If a town record DOES NOT exist with that given name attribute, then create a new town record with that name attribute, and associate that one to this user record
If any validations fail, do not create a user record or a town record and re-render the form.
I am having real trouble with this. This question suggests putting autosave on the belongs_to :town statement, as well as defining a method called autosave_associated_records_for_town. However: I just could not get that to work.
Appreciate it!
Please, try that solution. It works for me.
User
# user.rb
class User < ActiveRecord::Base
belongs_to :town
accepts_nested_attributes_for :town
validates :last_name, presence: true
end
Town
# town.rb
class Town < ActiveRecord::Base
has_many :users
validates :name, presence: true
end
Controller
# users_controller.rb
respond_to :html
def create
# ...
#user = User.new(user_params)
#user.town = Town.find_or_initialize_by(user_params[:town_attributes])
if #user.save
respond_with(#user)
else
render 'new'
end
end
# ...
def user_params
params.require(:user).permit(:last_name, :email, :town_id, town_attributes: [:name])
end
View
# users/_form.html.erb
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :last_name %><br>
<%= f.text_field :last_name %>
</div>
<%= f.fields_for :town, #town do |bldr| %>
<div class="field">
<%= bldr.label :name, 'Town name' %><br>
<%= bldr.text_field :name %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
UPDATE
Please consider to add validates_associated to user's validations as well.
Here is the related documentaion
class User < ActiveRecord::Base
belongs_to :town
accepts_nested_attributes_for :town
validates :last_name, presence: true
validates :town, presence: true
validates_associated :town
end
Generaly speaking, you could remove validates :town, presence: true in that case. Validations will work without it.

Rails don't show validation error messages on associated model

I have simple but frustrating problem with showing validation errors for comments of posts. Error partial shows errors for posts but despite validation works on comments, errors don't render.
comment form partial is inserted into post view:
<%= form_for([#post, #post.comments.build]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
errors partial
<% if object.errors.any? %>
<h2>Errors:</h2>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
models:
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
validates :title, :content, :presence => true
validates :title, length: { minimum: 3 }
validates :title, :uniqueness => true
end
class Comment < ActiveRecord::Base
belongs_to :post
validates :body, presence: true
validates :commenter, presence: true, length: { minimum: 3 }
end
I have been looking for answer for some time but can't get it working.
Add this line to the Post model
validates_associated :comments

RubyOnRails - Creating new objects with relations

i have 2 models, User and Technician
class User < ActiveRecord::Base
has_one :technician
end
class Technician < ActiveRecord::Base
belongs_to :user
validates :user, presence: true
end
When creating a new Technician and trying to associate with an existing User it gives the error: User cannot be blank
the view of Technician.new (form) is:
<%= form_for(#technician) do |f| %>
<% if #technician.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#technician.errors.count, "error") %> prohibited this technician from being saved:</h2>
<ul>
<% #technician.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :codigo %><br>
<%= f.number_field :codigo %><br><br>
<%= f.label :user_id %><br>
<%= f.select :user_id, options_for_select(User.all.map{|u|[u.nome, u.id]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
What am I doing wrong if, selecting an user from the select it won't associate it to the attribute user_id?
Thanks
Try using with collect like this
<%= f.select :user_id, User.all.collect {|u|[u.nome, u.id]}) %>
OR
If you are using Rails 4,you can use pluck
<%= f.select :user_id, User.pluck(:nome, :id))
For more details see this API
If that doesn't work,change your validation in Technician model like this
class Technician < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
end
Update
As you are using Rails4,you should be adding user_id to the permitted parameters like this
def your_params
params.require(:technician).permit(:user_id,:codigo)
end

Nested Form in Rails don't show nothing in Form

I want to create a nested form with relations between Clientes has_many enderecos, but in my form nothing is show up.
Look my models:
class Cliente < ActiveRecord::Base
has_many :enderecos, dependent: :destroy
validates :nome, :sexo, presence: true
validates :cpf, :email, :username, presence:true, uniqueness: true
has_secure_password
accepts_nested_attributes_for :enderecos
end
And endereco:
class Endereco < ActiveRecord::Base
belongs_to :cliente
end
And my form:
<%= form_for(#cliente) do |f| %>
<div class="field">
<%= f.text_field :nome, placeholder: 'Nome completo', size: '50px' %>
</div>
<% f.fields_for :endereco do |endereco_form| %>
<div class="field">
<%= endereco_form.label :cep, 'placeholder: ' %>
<%= endereco_form.text_field :cep, placeholder: 'CEP' %>
</div>
<div class="field">
<%= endereco_form.text_field :numero, placeholder: 'NĂºmero' %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
But inside nested part nothing is show up, what's happening?
You forgot the '=' sign:
<%= f.fields_for :endereco do |endereco_form| %>

rails, carrierwave, multiple images

I am working on my first rails application and I am attempting to setup multiple image uploads in a form. I have created a contest which has many contest entries, and contest entries can have many images. I have the contest entry piece working, but I am having trouble getting the image upload portion of the form working. I am following this tutorial http://lucapette.com/rails/multiple-files-upload-with-carrierwave-and-nested_form/ linked to from the carrier wave wiki.
contest entry model
class ContestEntry < ActiveRecord::Base
attr_accessible :body, :title, :contest_id, :entry_images_attributes
validates :user_id, presence: true
validates :title, presence: true, length: { maximum: 140 }
validates :body, presence: true
validates :contest_id, presence: true
belongs_to :contest
belongs_to :user
has_many :entry_images, as: :imageable
accepts_nested_attributes_for :entry_images
end
Entry image model
class EntryImage < ActiveRecord::Base
attr_accessible :alt, :image_path
belongs_to :imageable, :polymorphic => true
validates :image_path, presence: true
mount_uploader :image, ImageUploader
end
New entry form
<%= nested_form_for([:contest, #entry], :html => {:multipart => true}) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.hidden_field :contest_id %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<%= f.fields_for :entry_images do |builder| %>
<p>
<%= builder.label :alt %><br />
<%= builder.text_field :alt %>
</p>
<p>
<%= builder.label :image_path %><br />
<%= builder.file_field :image_path %>
</p>
<% end %>
<p><%= f.link_to_add "Add Image", :entry_images %></p>
<%= f.submit "Enter", class: "btn btn-large btn-primary" %>
<% end %>
<%= javascript_include_tag :defaults,"nested_form" %>
for some reason nothing shows up in the <%= f.fields_for :entry_images do |builder| %> block. It is just blank there is also no error message. if I switch it to
<%= f.fields_for :entry_image do |builder| %> and switch to using a form_for instead of the nested_form_for plugin all the fields show up but I get errors when I submit.
Any ideas?
Thanks,
Cory

Resources