Validate Uniqueness and Edit Form in Rails - ruby-on-rails

I have a form.
Same form is used for creating and editing...
In my model
validate_uniqueness_of :empID
is present..
and in my form on updating, I get the error that empID is already taken..
Is there any way i can exclude this validation in editing..

You can simply define that your validation should only come into effect on create
validates :empID, uniqueness: true, on: :create

"#TheChamp thing is in my edit form i have disabled the option to edit the id.. Since i want the id to be shown as disbaled in that page i cant remove those line for empID with a condition like if params[:action]==edit.. so hope this is the only solution.."
if all you want is for the empID not to be editable when the form is for an existing one... you can indeed check if the form is for editing and just display it like this:
(Assuming that the moel is in a variable called my_model)
# new_record? will only be true for a model that is being created, not edited
<% if my_model.new_record? %>
<%= f.select :empID, options_go_here %>
<% else %>
# don't display the field-here, instead just display the employee-info
<%= my_model.emp.name %>
<% end %>

Your application is doing exactly what you are instructing it to do.
You validate the uniqueness of the empID attribute which is on conflict upon the update request. Instead of only passing the validation upon it's create action you should think your logic through:
Is there any situation where multiple entries hold the same empID?
Why should the empID be unique? is it a primary key?
From my point of view it looks like empID defines a relation between the record and an emp model? if so adjust the validation to make it functional:
class Model < ActiveRecord::Base
belongs_to :emp
validates_presence_of :empID
end

Related

Rails multiple separate dropdown fields for has_and_belongs_to_many association

I have a two models associated with has_and_belongs_to_many
# post.rb
class Post < ApplicationRecord
has_and_belongs_to_many :keywords
I know that in views/posts/_form.html.erb I could do something like
form.select(:keyword_ids, Keyword.all.collect {|k| [ k.name, p.id ] }, multiple: true)
So then I would get one multi-select dropdown.
What if I want to have each keyword_id in a separate drop-down menu (not combined in one) and have all the keyword_ids from the separate dropdowns collected in one array when the form is submitted?
I tried solving it with fields_for and accepts_attributes_for but in that case, when updating the model the id that's sent from the form to the controller is always fixed to the ones of the keywords that the model had initially and it seems like it cannot be changed which makes sense since I understand this function is only supposed to change attributes of children, not change the child itself.
In the view
# views/posts/_form.html/erb
<% #post.keywords.each do |keyword| %>
<%= select_tag "post[keyword_ids][]", options_from_collection_for_select(Keyword.all, "id", "name", keyword.id) %>
<% end %>
Adding keyword.id in the options_from_collection_for_select will set the default value to the existing value if the model is updated.
In the controller
# post_controller.rb
def post_params
params.require(:post).permit({ keyword_ids: [] })
end

More than a simple nested form

campaign.rb
class Campaign < ActiveRecord::Base
has_many :items
accepts_nested_attributes_for :item
end
item.rb
class Item < ActiveRecord::Base
belongs_to :campaign
end
Campaign has 2 attributes: title and description
Item has 1 attirubte: name
I'll try explain myself by words, I want to create a nested form where they user insert the campaign's name and description but he can insert more than just 1 item, he can insert a list of items (in particular there will be a "+" button that when clicked a new item row will appear and the user can insert items).
At the end all is send all together clicking just one submit button.
How can I reach my goal with rails?
I answered a question just yesterday. Here's the link: Rails accepts_nested_attributes_for with f.fields_for and AJAX
I'll write out how it works & provide some resources to help give you some more ideas:
How It Works
Loading associative fields into a form is done by using f.fields_for
You'll do it like this:
#app/views/campaigns/new.html.erb
<%= form_for #campaign do |f| %>
<%= f.fields_for :items do |a| %>
<%= a.text_field :information %>
<% end %>
<% end %>
In order to get this to work, you have to build the associated ActiveRecord objects in the backend before you render the view, like this:
#app/controllers/campaigns_controller.rb
def new
#campaign = Campaign.new
#campaign.items.build
end
Adding Extra Fields Via Ajax
Adding extra fields with Ajax requires engineering a new solution to the issue
The way you do this is to take the f.fields_for text & put it into a partial. This partial can be called from the original view, as well as another view (which we can render through Ajax)
The Ajax part works by basically taking a request from your form (the ajax request), and then using another action in your controller to build a new ActiveRecord object & render another partial that will contain another form. This partial will then call the original f.fields_for partial, allowing you to render another field
Your Ajax can then extract the new field & append it to your page. The way you get around the id issue (keeping the IDs sequential & unique) is to employ the child_index method, and use Time.now.to_i to generate a timestamp
If you read my answer referenced at the top of this answer, all of this will make sense :)
Some great resources for this:
RailsCasts Nested Forms
Adding Fields With Ajax
A nice gem along with tutorial is available from ryanbates who is the author of railscasts.com site.You can use this and have a look at tutorial here
And also if you want to try manually use the fields_for while writing in the form like here and manage some jquery code for add or remove.

Rails scaffolding belongs_to - showing #<MyClass:xxxx>

Experienced Java developer, new to Rails - wondering about belongs_to relationship in scaffolding.
Saw another answer like this
Does rails scaffold command support generate belongs_to or many to many model middle table migration info?
and followed the rails generate scaffold_controller obj:references pattern.
The index/show page is showing #<MyClass:xxxx> instead of the string I want - is there a method in the target class (parent side of the belongs_to) I need to override to specify the identifier?
Also in the edit view, it looks like it's trying to modify the reference as a string rather than as drop-down - is there something I need to specify to make that happen?
Thanks!
BTW - I was able to get similar scaffolding to work in Django and Grails, where the foreign key turned into a drop-down; I'm hoping Rails is equally easy and I'm just missing it.
You can override the #to_s method on the instances, as it is the one being called.
class FooDoodle < ActiveRecord::Base
def to_s
name
end
end
That's when showing a record.
However, when you're actually using the form to set the associations, scaffold will only generate an input field in the view so you can enter the id. You could have a dropdown menu for example, but the options for that dropdown would somehow have to be selected in a manner.
For example, if there are 2000 possible associated records, which ones do you show? Do you show the 2000? Only the first 10? That logic would go into your controller.
So, for example:
class FooDoodlesController < ApplicationController
def edit
#foodoodle = FooDoodle.find(params[:id])
#friends = #foodoodle.possible_friends # or else
end
end
and using select and options_for_select as choices
# _form.html.erb
<%= form_for #foodoodle do |f| %>
<%= f.label :friend %>
<%= f.select :friend, #friends.map{ |p| [p.to_s, p.id] } %>

Rails (3) validation of non-ActiveRecord field

I have a model with a corresponding form, for which I use ActiveRecord validations. At the bottom of the form I'd like to have a single confirmation checkbox which should not be persisted, but which must be checked for the form to be submitted. I'd also like any errors that stems from this checkbox not being checked to display alongside the ActiveRecord errors.
Now I could cobble something together in the controller manually, but I'm wondering if there is a built-in, cleaner way to handle this kind of situation?
I think you should add this in your model:
validates_acceptance_of :check_me
attr_accessor :check_me
attr_accessible :check_me # if you already have attr_accessible defined in your model
and this in your view:
<%= form_for #your_model do |f| %>
# some code
<%= f.check_box :check_me %>
<% end %>

Rails: how to save form data after posting

When I use form_for :model the data is saved when I submit the form.
However when I use form_tag, the data is lost after the form is processed.
I need to use form_tag because I have two models in one form.
Is there a way to save form data with form_tag?
You are making two incorrect assumptions in your question. First, form_tag is not necessary or even recommended for multiple-model forms; Second, form_tag doesn't do anything fundamentally different from form_for, you are most likely not formatting the field names correctly for your controller.
In order to create a form with nested models, you need to use the fields_for helper in conjunction with form_for. The relationship needs to be defined first in the model with accepts_nested_attributes_for. Since you have not given us any information about your models, I will give you a made-up example:
class Person < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
end
class Address < ActiveRecord::Base
belongs_to :person
end
This tells ActiveRecord that the Person model can accept attributes for Address, and will pass along the attributes to the correct model to be created.
<% form_for :person do |p| %>
<% p.fields_for :address do |a| %>
use the a form builder to create
fields for the address model here
<% end %>
<% end %>
chaining the fields_for helper from the p form builder lets the helpers generate attributes in the correct format.
More information: Nested Model Forms
Pretty much the same way as before except you'll need to build the params. You can look at your log to see how params are being sent.
eg.
def create
#silly_hat = SillyHat.new( :name => params[:name], :size => params[:size], :colour => params[:colour] )
if #silly_hat.save
...

Resources