1

I am following the rails cast 263 on client side valuation. I have the code in place, though it is not validating the errors live for me. The errors only show after submitting the form.

application.html.erb:

  <%= stylesheet_link_tag "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= javascript_include_tag :defaults, "rails.validations" %>
  <%= csrf_meta_tags %>

client_side_validations.rb:

 ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
   unless html_tag =~ /^<label/
     %{<div class="field_with_errors">#{html_tag}<label for="#{instance.send(:tag_id)}" class="message">#{instance.error_message.first}</label></div>}.html_safe
   else
     %{<div class="field_with_errors">#{html_tag}</div>}.html_safe
   end
 end

form.html.erb:

<%= form_for @user, :validate => true do |f| %>
  <% if @user.errors.any? %>
    <div class="error_messages">
      <h2>Form is invalid</h2>
      <ul>
        <% @user.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

    <div class="field">
        <%= f.label :email %><br/>
        <%= f.text_field :email %>
    </div>
    <div class="field">
        <%= f.label :password %><br/>
        <%= f.password_field :password %>
    </div>
    <div class="field">
        <%= f.label :username %><br/>
        <%= f.text_field :username %>
    <div class="field">
        <%= f.label :zip_code %><br/>
        <%= f.text_field :zip_code %>
    </div>
    </div>

application.js:

//= require jquery
//= require jquery.ui.all
//= require jquery_ujs
//= require jquery.magnific-popup.js
//= require jquery.purr
//= require rails.validations
//= require best_in_place
//= require_tree .
Cornelius Wilson
  • 2,844
  • 4
  • 21
  • 41
  • When you tab off a field that has validations defined, the client_side_validations JavaScript code in rails.validation.js should fire. If you debug the JS in your browser, is the code within `executeValidates = function(context)` firing? – cschroed Nov 19 '13 at 18:17
  • @cschroed When I view page source I actually get a `Failed to load resource: the server responded with a status of 404 (Not Found)`. Coming from the link http://localhost:3000/javascripts/defaults.js. Could that be the reason? – Cornelius Wilson Nov 19 '13 at 19:08
  • Yes, that seems to be the start of the problem. I've suggested an alternative option. – cschroed Nov 19 '13 at 19:30

1 Answers1

3

Original Suggestion: Link to JS in application.js.

Rather than linking to the rails.validations.js from application.html.erb:

<%= javascript_include_tag :defaults, "rails.validations" %>

You may want to do this in your app/assets/javascripts/application.js file:

//= require rails.validations

That's how I connect into additional JavaScript files.

I don't know much about Rails 2, but I think that there was a shift in Rails 3 so that now application.html.erb is used to link to application.js and then all other JS files are linked to from there. It looks like :default might not work how it used to. RailsCasts are super helpful but some of the episodes that were created a few years ago have code samples that have changed in recent versions of Rails.

Edit 1: Make sure rails.validations.js was installed into app/assets/javascripts.

In the RailsCast the rails g client_side_validations:install command puts rails.validations.js into the project. Apparently this doesn't always work and you can call rails g client_side_validations:copy_assets to get it dropped into app/assets/javascripts (See: Can't include js file for client slide validation).

Edit 2: In Rails 4, fix compatibility bugs.

It looks like client_side_validations doesn't work in Rails 4 and the gem is no longer maintained (See: https://github.com/bcardarella/client_side_validations).

In Rails 3, in action_view\helpers\form_helper.rb, the apply_form_for_options! method is:

def apply_form_for_options!(object_or_array, options)

In Rails 4, it is:

def apply_form_for_options!(record, object, options)

If you look at the client_side_validations code, its version is:

def apply_form_for_options!(object_or_array, options)
  super
  options[:html][:validate] = true if options[:validate]
end

That matches the Rails 3 definition. We only get two arguments but then we call super which blows up because Rails 4 expects three arguments.

If you are feeling brave, you could fork the client_side_validations gem and work through these Rails-4-compatibility issues. But I would suspect that there might be quite a few pieces to update since this gem had to be so tightly integrated with the FormHelper.

Sorry that doesn't immediately solve your problem. Good luck!

Community
  • 1
  • 1
cschroed
  • 6,304
  • 6
  • 42
  • 56
  • That does not work. `[Error] ReferenceError: Can't find variable: jQuery (anonymous function) (rails.validations.js, line 5)` – Cornelius Wilson Nov 19 '13 at 19:33
  • This means we're now connected to rails.validations.js but it doesn't know what jQuery is. Do you have `gem 'jquery-rails'` installed in your app? And do you have `//= require jquery` in `application.js`? – cschroed Nov 19 '13 at 20:04
  • Yes I have both there – Cornelius Wilson Nov 19 '13 at 20:12
  • One more thing to check: is the `//= require jquery` line listed above the `//= require rails.validations` line? – cschroed Nov 19 '13 at 20:37
  • Yes that's there. I added the application.js file to posting so you can see what I have. One error I do get is `couldn't find file 'rails.validations'` when loading pages. – Cornelius Wilson Nov 19 '13 at 20:46
  • When you did the install did the `rails.validations.js` make it into your app? I've updated the answer with an additional suggestion on this. – cschroed Nov 19 '13 at 21:16
  • I restarted server and the error goes away (should've done that before!) but I get `wrong number of arguments (3 for 2)`. It's for this line `<%= form_for @user, :validate => true do |f| %>` – Cornelius Wilson Nov 19 '13 at 22:39
  • Added Edit 2 to the answer to explain why this error occurs in Rails 4. – cschroed Nov 20 '13 at 00:12