Rails Form - Check for pre-existing data and populate fields - ruby-on-rails

I'm working on a rails app that allows field agents to report ticket(s) on behalf of clients. I am capturing the data using a model called "submission" where the agents can input the client's details and submit one or more tickets for the client.
I want to ensure that if a client already exists then a new record is not created for the same client. I would also like to ensure that if a client has a name similar to a pre-existing record then the clients don't get mixed up e.g: 2 people named John Smith.
My current submission form:
<%= form_for(#submission) do |f| %>
# some submission fields here ...
<h4>Client Details</h4>
<%= f.fields_for :client do |c| %>
<div class="row">
<div class="field col-xs-6">
<%= c.label :first_name %><br>
<%= c.text_field :first_name, class: 'form-control' %>
</div>
<div class="field col-xs-6">
<%= c.label :last_name %><br>
<%= c.text_field :last_name, class: 'form-control' %>
</div>
</div>
# more client fields....
<% end %>
<% end %>
How can I add a function to check for existing records that match the first and last names when you fill in the fields? Also, how can I ensure that if 2 clients exist with the same name then this can be identified? Could I maybe use the phone number as a unique identifier?
I know my question is a bit vague but I am unsure of how best to tackle this issue (autocomplete? maybe a checkbox that has options for new or existing client?)
Any help would be most appreciated.

You probably want to use Rails validations to ensure the first name and last name of client will not repeat. For example:
class Client < ActiveRecord::Base
validates :first_name, uniqueness: true
validates :last_name, uniqueness: true
end
But this will reject any that has same first name but different last name or the other case. In this situation you might search for custom validation method:
class Client < ActiveRecord::Base
validate :same_full_name
def same_full_name
# or different logic/additional condition
if Client.exists?(first_name: first_name, last_name: last_name, phone_number: phone_number)
errors.add("Client with this name exists.")
end
end
end
This will prompts error when user tries to submit the form. When Rails validation failed they will be redirected to this page(assuming that standard REST actions applied) and see the error message(if there's any flash or error message in your view).
If instant error prompt is preferred, you may want a JavaScript client integration with Rails validation such as client_side_validations gem, or use jquery validation for pure Javascript validation.
For the problem stated in the comment:
If a client does already exist in the database, how can I populate the form with this data and save the submission with the same client?
This depends on the web flow, another of the solution might be using ajax to call a controller action to check whether the client exists. If it does then you can use jQuery to populate the returned client data(from the controller) to the form, instead of doing the validation.

Related

How to save data to multiple tables in Rails

I am using Devise for authentication in my app and got a model named as "Users". I created an another model for Company informations. I generated the migration with references and everything is okay.
I want to add user informations to users table and company informations to companies table in same registration view.
Also both users and companies tables got the same field as "name".
I tried to specify it as ;
<%= f.text_field :company["name"], autocomplete: "company_name" %>
<%= f.text_field :company[:name], autocomplete: "company_name" %>
<%= f.text_field :companies[:name], autocomplete: "company_name" %>
And i got the errors ;
undefined method `' for #<User:0x00007fd5588cb588>
no implicit conversion of Symbol into Integer
I think somehow i should override devise_controller but i want to learn the general practice for these kind of situations.
Sum: I want to save data to different tables which has same column names in database.
Assuming user belongs_to company and you want to save user and their associated company from one form submit, you can use fields_for for this
<%= f.fields_for :company do |cf| %>
<%= cf.text_field :name %>
<% end %>
This will require accepts_nested_attributes_for :company in User.

Moving error conditionals out of the view. -Rails

I have a form that has a text field for name, it has a presence validation on it. When a user forgets to input the name the text field turns red this is all fine but I'd like to clean up my view a little bit but I'm not sure how? Maybe a helper? Maybe a method? I'm a bit new to rails and I'm looking for some advice on this problem. Here is my code for the view.
VIEW
<% if f.object.errors[:name].present? %>
<%= f.text_field :name, :class => 'alert' %>
<div class="validation">
<% f.object.errors[:name].each do |error| %>
<%= error %>
<% end %>
</div>
<% else %>
<%= f.text_field :name %>
<% end %>
It's a pretty standard if else statment but I'd think its a little too ugly for the view.
You can achieve a similar result using your model validation. If you require a presence validation on a model, then it will tell the user the field cannot be blank. This would allow you to tell the user they cannot leave a form field blank without manually coding this in your views.
Example: Post Model - app/models/post.rb
class Post < ActiveRecord::Base
validates :title, :presence => true
validates :body, :presence => true
end
If the user now attempts to submit the form with either Title or Body empty then they will be asked to resubmit the form, with a little tool tip saying "Please fill out this field".
No logic is needed in the view to achieve this, simply validate presence in your model.

Date Issue with Ruby on Rails

I just working on a simple Ruby on Rails application that keeps the data information of staff, but I realized that I needed a way to check that the date of employment will definitely need to be the beginning of the date of resignation.
<div class="field">
<%= f.label :date_of_employment %><br />
<%= f.date_select :date_of_employment, :start_year =>1990 %>
</div>
<div class="field">
<%= f.label :date_of_resignation %><br />
<%= date_select :date_of_resignation, :start_year => Time.now %>
You should check validates timeliness gem, if you are happy to add outside code to your project. It adds all kinds of time/date based validations.
Including validating that one field is before/after another. For instance, the following commands could be used in you model:
validates_datetime :date_of_resignation, :after => :date_of_employment
This gem doesn't rely on javascript to work, it's pure Ruby.
One of the simple solution you can consider is to have a javascript function to verify these two date on form submit. This way your server does not need to process invalid data.
We can perform validation at Rails model level before saving to database. For example these lines of code in the model will validate the data before saving
validate :verify_date
def verify_date
errors.add("Invalid date") if date_of_resignation < date_of_employment
end

Why is this validation applying?

I created a form ("Form1") and a validation to go along with it. Then I created a different form ("Form2") for another purpose but the validation method for "Form1" is being triggered when I submit Form2
Form2 and Form1 are both being submitted to the same database, but I didn't think the validation would apply to both of them, because attribute/method names were different in the forms
Form 1
<%= form_for(#guess) do |f| %>
<% if #guess.errors.any? %>
<div class="field">
<%= f.label(:math, "I think many students will fail Math") %>
<%= f.check_box(:math) %> </br>
</div>
<div class="field">
<%= f.label(:french, "I think many students will fail French") %>
<%= f.check_box(:french) %> </br>
</div>
I do the same for 6 subjects. Students are required to select 3 subjects that might create fails..
Validation for Form1 in model Guess.rb
validates_inclusion_of :possible_assessment_failures, :in => 1..3, :message => "You must check off 1,2 or 3 different assessments for question 1"
...
def possible_assessment_failures
[math, french, english, science, history, geography].select{|x| x }.count
end
Comment: I assumed that this validation got triggered because the methods in the form (:french, :math etc) were in the array [math, french...] in the validation...I'm guessing that's wrong
--
Form2
In the controller....
#teacher = Guess.new
in the view...
<div class="field">
<%= f.label(:MrSmith, "MrSmith") %>
<%= f.select:MrSmith, 1..6 %> </br>
</div>
So why is the validation for form1 getting called when I submit form2?
As mentioned, I thought the validation got called for form1 because the methods in the array in the validation (i.e. the names of the subjects
[math, french, english, science, history, geography].select{|x| x }.count
were named in the form
<%= f.check_box(:math) %>
so if my Form2 has different attributes (like teacher's names
<%= f.select:MrSmith, 1..6 %>
I don't understand why that would trigger a validation with the names of subjects (math, french etc) in it?
I'm assuming that's totally wrong thinking on my part. So what triggers the validation and how do I get it not to apply on form2?
All of the validations in Guess.rb are called whenever the guess model is saved (by default, you can disable them with save(:validate => false)).
It's not generally a good idea to only apply some validations when saving a model since you'll lose the guarantee that your database is consistent with all of your validations.
If you really want to do it, you could create a new attribute and only run the validation if that attribute is true, see this answer https://stackoverflow.com/a/3956701/625365

Adding "linked accounts" (e.g., Twitter, Facebook) to a Rails 3 website

This isn't a question about how to use Twitter or Facebook API, but a simpler one about how to keep the databases in sync. What I want to do is to create a NEW linked account, and then attach that to the current user. I KNOW that my code currently is nonfunctional:
On the Edit Profile page
<%= f.label :account %> <i>(link another account to this profile)</i><br />
<% form_for #user.linked_accounts do |f| %>
<%= f.text_field :username %>
<%= f.collection_select :service, User::POSSIBLE_SERVICES, :to_s, :to_s,
:include_blank => true
%>
<%= f.submit %>
<% end %>
How do I get it to submit into a devise database? It's definitely the " form_for #user.linked_accounts " I need to fix. I changed it to #user and I get a no-method error because :service is only defined in a linked account. I think that what I need to do is to create a new linked account, and then do the form_for #user.new_account.
The error I receive is:
SQLite3::SQLException: no such column: linked_accounts.user_id: SELECT "linked_accounts".* FROM "linked_accounts" WHERE ("linked_accounts".user_id = 1)
There is a railscast that deals with this. It uses an authorisations table which belongs_to the user table so you can add twitter, facebook etc... to the user
The cast is over 2 episodes and uses omniauth which is a really neat solution. You can find them here
http://railscasts.com/episodes/235-omniauth-part-1
http://railscasts.com/episodes/236-omniauth-part-2
if i correctly understand your problem it's may be a solution for you to :
create a new model to contain social network information
use nested model to allow adding social via the edit user form
And that's it

Resources