2016-10-25 1 views
0

Je ne suis pas vraiment expérimenté chez Ruby on Rails alors j'ai besoin de votre aide.Éviter les exceptions en violant une validation

Visit.rb

class Visit < ActiveRecord::Base 

    belongs_to   :employee 
    belongs_to   :visitor 
    default_scope -> { order(:created_at) } 

    validates :start,   presence: true,  uniqueness: {scope: [:end, :visitor_id]} 
    validates :end,    presence: true 
    validates :visitor_id,  presence: true 
    validates :employee_id,  presence: true 
    validate :valid_date_range_required 

    def valid_date_range_required 
     if (start && end) && (end < start) 
      errors.add(:end, "must be after start") 
     end 
    end 
end 

schema.rb

create_table "visits", force: true do |t| 
    t.datetime "created_at",       null: false 
    t.datetime "updated_at",       null: false 
    t.date  "start" 
    t.date  "end" 
    t.integer "idVisit" 
    t.integer "employee_id" 
    t.integer "visitor_id" 
    t.string "status",  default: "Confirmed" 
    end 

    add_index "visits", ["start", "end", "visitor_id"], name: "index_visits_on_start_and_end_and_visitor_id", unique: true 

Au cours de mes tests, si je ne respecte pas la validation sur le caractère unique ou sur: valid_date_range_required ma demande soulève une sorte de blocage d'exception lui-même (par exemple: Le premier argument dans le formulaire ne peut pas contenir ni être vide). Au lieu de cela je ne voudrais pas que l'application le montre, mais je voudrais que l'application montre une sorte de message d'erreur pendant la création de la visite afin que l'utilisateur puisse remplir le formulaire d'une manière appropriée.

Est-ce que quelqu'un d'entre vous peut m'aider à comprendre une façon de le faire?

EDIT:

visits_controller.rb

class VisitsController < ApplicationController 
    before_action :logged_in_employee, only: [:create, :destroy] 
    before_action :correct_employee, only: [:destroy, :update ] 

    def create 
     @visit = current_employee.visits.build(visit_params) 
     if @visit.save 
      flash[:success] = "Visit added" 
      redirect_to employee_path(session[:employee_id], :act => 'guestsVisits') 
     else 
      @visits = current_employee.visits.all 
      @employee = current_employee 
      @errors = @visit.errors.full_messages 
      flash[:danger] = @errors 
      render 'employees/guestsVisits' 
     end 
    end 



    private 

     def visit_params 
      params.require(:visit).permit(:start, :end, :visitor_id, :employee_id) 
     end 
end 

guestsVisits.rb (mon avis)

<div class="jumbotron3 text-center"> 
    <div class="row"> 
    <h1>Guests Visits</h1> 
    <hr> 
    <%=render :partial =>"layouts/sidebar"%> 
    <div class="panel3"> 
     <div class="panel-body"> 
      <% if logged_in? %> 
       <%=render :partial =>"shared/error_messages"%> 

        <a class="btn icon-btn btn-success pos" data-toggle="modal" data-target="#visitModal"> 
       <span class="glyphicon btn-glyphicon glyphicon-plus img-circle text-success"></span> 
       Add a visit 
       </a> 

       <div id="visitModal" class="modal fade" role="dialog"> 
       <div class="modal-dialog"> 

       <div class="modal-content"> 

       <div class="modal-header"> 
       <button type="button" class="close" data-dismiss="modal">&times;</button> 
       <h4 class="modal-title">Add a visit</h4> 
       </div> 

       <div class="modal-body"> 
       <%= form_for(@visit) do |f| %> 

       <%= f.label :start_date %> 
       <%= f.date_field :start, class: 'form-control',:value => (f.object.start.strftime('%m/%d/%Y') if f.object.start) %> 
       <%= errors_for @visit, :start %><%if @visit.errors.any?%><br><%end%> 

       <br> 
       <%= f.label :end_date %> 
       <%= f.date_field :end, class: 'form-control',:value => (f.object.end.strftime('%m/%d/%Y') if f.object.end) %> 
       <%= errors_for @visit, :end %><%if @visit.errors.any?%><br><%end%> 

       <br> 
       <%= f.label :Visitor %> 
       <%= f.collection_select :visitor_id, Visitor.all, :id, :full_name, { :class=> "form-control", :include_blank => ''}%> 
       <%= errors_for @visit, :visitor_id %><%if @visit.errors.any?%><br><%end%> 
       <br> 
       <%= f.submit "Add visit", class: "btn btn-primary btn-color" %> 
       <% end %> 
       </div> 

       <div class="modal-footer"> 
       <button type="button" class="btn btn-info" data-dismiss="modal">Close</button> 
       </div> 

       </div> 
       </div> 
       </div> 
       <% end %> 
       </div> 
     </div> 
    </div> 
    </div> 

error_messages.rb

<% if @visit && @visit.errors.any? %> 
    <div id="error_explanation"> 
    <div class="alert alert-danger"> 
     <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a> 
     The form contains <%= pluralize(@visit.errors.count, "error") %>.Open the modal for more details 
    </div> 
    </div> 
<% end %> 

Ce que je dois est que, en ajoutant la date de fin qui vient avant la date de début ou l'ajout d'un enregistrement (début, fin, visiteur) qui est déjà dans la base de données, je peux montrer l'erreur dans mon modal sans blocage de toute l'application à cause de Le premier argument dans le formulaire ne peut pas contenir de zéro ou être vide exception ou similaire.

Merci beaucoup.

+0

peut vous poster le test? –

+0

Votre contrôleur doit gérer cela. Utilisez-vous des modèles erb pour rendre vos pages de création ou une page personnalisée? Les modèles générés par les rails restituent automatiquement les erreurs de modèle sur les champs dont les validations échouent. Vous devez simplement confirmer qu'une exception est générée pour une attribution de modèle non valide. – Pyrce

+0

J'ai un modal contenant un formulaire pour créer une visite. Je voudrais que si je choisis une date de fin qui vient avant la date de début ou si j'essaie de créer une visite ayant le même début, fin et visiteur d'un autre déjà enregistré dans la db, après avoir cliqué sur le bouton pour le créer, une erreur dans le modal apparaît expliquant le problème au lieu d'une exception bloquant tout, mais je ne sais pas comment le faire. – Benny

Répondre

0

Voici comment créer un message personnalisé pour les erreurs liées à l'unicité.

validates :start, presence: true, uniqueness: {scope: [:end, :visitor_id],  
message: ->(object, data) do 'Each start can only have one visitor and one end.' 
end 
} 

class VisitsController 

    def create 
    @visit = Visit.find(params[:id]) 
    if @visit.save 
     flash.now[:success] = 'Visit created' 
     redirect_to @visit 
    else 
     @errors = @visit.errors.full_messages 
     flash[:danger] = @errors 
     redirect_to root_url 
    end 
    end 

http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html

+0

Il est souvent préférable d'utiliser 'save! ', Puis de' rescue' toutes les exceptions qui pourraient avoir échoué. En outre, lors de la liaison à la documentation, essayez d'obtenir la version actuelle et non historique. – tadman

+0

Même en faisant cela, l'exception se produit et bloque tout. – Benny

+0

@AnM Je pense que vous devez afficher la vue et le contrôleur. –