How do I add validation to a partial in Rails 3? - validation

This is the error I am getting:
ArgumentError in Home#index
Showing /app/views/clients/_form.html.erb where line #6 raised:
You need to supply at least one validation
Extracted source (around line #6):
3: render :partial => "clients/form",
4: :locals => {:client => client}
5: -%>
6: <% client ||= Client.new
7: new_client = client.new_record? %>
8: <%= form_for(client, :html => { :class=>"ajax-form", :id => "client-ajax-form"}, :remote => true, :disable_with => (new_client ? "Adding..." : "Saving...")) do |f| %>
9: <div class="validation-error" style="display:none"></div>
My client model looks like this:
class Client < ActiveRecord::Base
# the user model for the client
belongs_to :user
has_many :projects, :order => 'created_at DESC', :dependent => :destroy
#The following produces the designers for a particular client.
#Get them from the relations where the current user is a client.
has_one :ownership, :dependent => :destroy
has_one :designer, :through => :ownership
validates :name, :presence => true,
:length => {:minimum => 1, :maximum => 128}
validates :number_of_clients
def number_of_clients
Authorization.current_user.clients.count <= Authorization.current_user.plan.num_of_clients
end
end
This is how the app/views/client/_form.html.erb partial looks:
<%#
Edit a single client
render :partial => "clients/form",
:locals => {:client => client}
-%>
<% client ||= Client.new
new_client = client.new_record? %>
<%= form_for(client, :html => { :class=>"ajax-form", :id => "client-ajax-form"}, :remote => true, :disable_with => (new_client ? "Adding..." : "Saving...")) do |f| %>
<div class="validation-error" style="display:none"></div>
<div>
<label for="client_name"><span class="icon name-icon"> </span></label>
<input type="text" class="name" size="20" name="client[name]" id="client_name" value="<%= client.name %>" > <%= f.submit(new_client ? "Add" : "Save", :class=> "green awesome")%>
</div>
<% end %>
<% content_for(:deferred_js) do %>
// From the Client Form
$('#client-ajax-form')
.bind("ajax:success", function(evt, data, status, xhr){
console.log("Calling Step View");
compv.updateStepView('client', xhr);
});
<% end %>
How do I fix that error ?

The problem is caused by the following line in your model:
validates :number_of_clients
When you use validates (s in the end) you have to follow the default rails validations like you did with the name validation. However, when you use a custom method to do the validation, you should use validate instead. So this should work:
validate :number_of_clients

Related

Padrino and sequel nested attributes form

I am trying to make a form for storing data hierarchy through the associations.
My structure of database is
meta
- ID (PK)
version
- meta_id (FK of meta)
- ID (PK)
- lang (FK from lang ...)
- ....
data
- ID (FK of version)
I need to store multiple language content under one ID.
Models are
class Meta < Sequel::Model(:link_meta)
one_to_many :version
end
class Version < Sequel::Model(:link_version)
one_to_one :meta, key: :meta_id
one_to_many :data, key: :id
one_to_one :lang, key: :lang
end
class Link < Sequel::Model(:link)
plugin :timestamps, :create => :created, :update => :updated
many_to_one :version, key: :id
end
And my form for creating input is.
<% form_for :links, url(:links, :create), :class => 'form-horizontal' do |f| %>
<%= partial 'links/form', :locals => { :f => f } %>
<% end %>
And this is my partial
<% f.fields_for :version, :class => 'form-horizontal' do |cz| %>
<%= cz.hidden_field :lang, :value => Lang.select(:id).where(:lang => "cz").map(:id) %>
<% cz.fields_for :data, :class => 'form-horizontal' do |link| %>
<% error = #links.errors.key?(:url) && #links.errors[:url].count > 0 %>
<fieldset class='control-group <%= error ? 'has-error' : ''%>'>
... form content
</fieldset>
<% end %>
<% f.fields_for :version, :class => 'form-horizontal' do |en| %>
<%= en.hidden_field :lang, :value => Lang.select(:id).where(:lang => "cz").map(:id) %>
<% en.fields_for :data, :class => 'form-horizontal' do |link| %>
<% error = #links.errors.key?(:url) && #links.errors[:url].count > 0 %>
<fieldset class='control-group <%= error ? 'has-error' : ''%>'>
... another form content
</fieldset>
<% end %>
<% end %>
But it fails on
undefined method `data' for [:class, "form-horizontal"]:Array
I tried different association combinations etc, I feel lost.
Thanks
Levi

undefined method `Password_field' error using Rail3

I am getting the following error while trying to do reset password by sending sending the link to email and open that link from that email.
Error:
NoMethodError in Admins#editpass
Showing C:/Site/swargadwar_admin/app/views/admins/editpass.html.erb where line #16 raised:
undefined method `Password_field' for #<ActionView::Helpers::FormBuilder:0x21c0108>
Extracted source (around line #16):
13: <% end %>
14: <p>
15: <label for "new_pass">New Password :</label>
16: <%= f.Password_field :password,placeholder:"Enter your new password" %>
17: </p>
18: <p>
19: <label for "new_pass">Confirm New Password :</label>
Rails.root: C:/Site/swargadwar_admin
Application Trace | Framework Trace | Full Trace
app/views/admins/editpass.html.erb:16:in `block in _app_views_admins_editpass_html_erb___904659562_17338176'
app/views/admins/editpass.html.erb:2:in `_app_views_admins_editpass_html_erb___904659562_17338176'
Please check my below codes and let me to know where i did the mistake as well as try to help me to resolve this.
views/admins/editpass.html.erb
<center>
<%= form_for :admin,:url => {:action => "setpass",:id => params[:id] } do |f| %>
<% if #admin.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#admin.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #admin.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<label for "new_pass">New Password :</label>
<%= f.Password_field :password,placeholder:"Enter your new password" %>
</p>
<p>
<label for "new_pass">Confirm New Password :</label>
<%= f.Password_field :password_confirmation,placeholder:"confirm your new password" %>
</p>
<p>
<%= f.submit "Submit" %>
</p>
<% end %>
</center>
controller/admins_controller.rb
class AdminsController < ApplicationController
def create_registration
#admin=Admin.new(params[:admin])
if #admin.save
flash[:notice]="User has created successfully"
flash[:color]="valid"
redirect_to :action => "index" , :controller => 'homes'
else
flash[:alert]="User could not created"
flash[:color]="invalid"
render 'homes/index'
end
end
def forget
#admin=Admin.new
end
def resetpass
#admin=Admin.find_by_email(params[:admin][:email])
if #admin.email==params[:admin][:email]
UserMailer.registration_confirmation(#admin).deliver
flash[:notice]="Check your email to reset the password"
flash[:color]="valid"
redirect_to :action => "index" , :controller => 'homes'
else
flash[:alert]="Invalid email id"
flash[:color]="invalid"
render 'homes/index'
end
end
def editpass
#admin=Admin.new
end
def setpass
#admin=Admin.find(params[:id])
if #admin.update_attributes(params[:admin])
flash[:notice]="Your password has updated successfully"
flash[:color]="valid"
redirect_to :action => "index" , :controller => 'homes'
else
flash[:alert]="Your password could not updated"
flash[:color]="invalid"
render 'homes/index'
end
end
end
model/admin.rb
class Admin < ActiveRecord::Base
attr_accessible :email, :password_hash, :password_salt, :picture, :user_name,:password_confirmation,:password, :remember_me
attr_accessor :password
attr_accessor :remember_token
before_save :encrypt_password
mount_uploader :picture, PictureUploader
EMAIL_REGEX = /\A[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
validates :user_name, :presence => true, :length => {:in => 3..10}
validates :password, :confirmation => true
validates_length_of :password, :in => 6..20, :on => :create
has_secure_password
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
def Admin.digest(string)
cost = 10
BCrypt::Password.create(string, cost: cost)
end
# Returns a random token.
def Admin.new_token
SecureRandom.urlsafe_base64
end
# Remembers a user in the database for use in persistent sessions.
def remember
self.remember_token = Admin.new_token
update_attribute(:remember_digest, Admin.digest(remember_token))
end
def forget
update_attribute(:remember_digest, nil)
end
end
Please help me.
You just have a typo: The method is named password_field, not Password_field. Just change the two method calls in app/views/admins/editpass.html.erb and you are done.

undefined method session_path when using devise

I am getting undefined method 'session_path' for #<#<Class:0x9859218>:0x8ebcbd0> when using devise with my custom controller and view, can anybody shed some light on what I have done wrong?
routes:
devise_for :users, :skip => [:sessions]
as :user do
get 'account/login' => 'account#login', :as => :new_user_session
post 'account/login' => 'account#login_user', :as => :user_session
delete 'account/logout' => 'account#logout', :as => :destroy_user_session
end
controller:
AccountController < Devise::SessionsController
def login
self.resource = resource_class.new(sign_in_params)
clean_up_passwords(resource)
respond_with(resource, serialize_options(resource))
end
def login_user
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_flashing_format?
sign_in(resource_name, resource)
yield resource if block_given?
respond_with resource, location: after_sign_in_path_for(resource)
end
def logout
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
set_flash_message :notice, :signed_out if signed_out && is_flashing_format?
yield if block_given?
respond_to_on_destroy
end
view:
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<ul>
<li>
<%= f.label :login, "Email", :class => labels %>
<%= f.email_field :login, :autofocus => true, :class => "wideinput" %>
</li>
<li>
<%= f.label :password, :class => "labels" %>
<%= f.password_field :password, :autocomplete => "off" %>
</li>
<li class='button'>
<%= submit_tag "Login", :class => "btn1" %>
</li>
</ul>
<% end %>
Try to change this line
post 'account/login' => 'account#login_user', :as => :user_session
to
post 'account/login' => 'account#login_user', :as => :session

Devise user sign up form with business model

I'm trying to create a user sign up form with Devise that will also allow for the creation of a new business associated with that user.
I have a business model setup and can't seem to save the business information to the database. Below is my code, I'm fairly new to rails so I apologize if I'm asking a question with an obvious answer.
new.html.erb (user)
<div class="content">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1>Sign Up</h1>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<label>Name</label>
<%= f.text_field :username, :autofocus => true, :class => "form-control", :placeholder => "Full Name" %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.text_field :email, :class => "form-control", :placeholder => "Email" %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, :class => "form-control", :placeholder => "Password" %>
<p class="help-block">Passwords must be a minimum of 8 characters.</p>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, :class => "form-control", :placeholder => "Retype Password" %>
</div>
<!-- Business Infomation -->
<h2>Business Information</h2>
<%= f.fields_for :business do |b| %>
<div class="form-group">
<%= b.label :name %>
<%= b.text_field :name, :class => "form-control", :placeholder => "Business Name" %>
</div>
<div class="form-group">
<%= b.label :address %>
<%= b.text_field :address, :class => "form-control", :placeholder => "Address" %>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<%= b.label :city %>
<%= b.text_field :city, :class => "form-control", :placeholder => "City" %>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<%= b.label :state %>
<%= b.text_field :state, :class => "form-control", :placeholder => "State" %>
</div>
</div>
<div class="col-sm-4">
<div class="form-group">
<%= b.label :zip %>
<%= b.text_field :zip, :class => "form-control", :placeholder => "ZIP" %>
</div>
</div>
</div>
<div class="form-group">
<%= b.label :country %>
<%= b.text_field :country, :class => "form-control", :placeholder => "Country" %>
</div>
<% end %>
<div class="well">
<%= f.submit "Sign Up", :class => "btn btn-primary" %>
</div>
<% end %>
</div>
</div>
user.rb
class User
include Mongoid::Document
include Mongoid::Paperclip
rolify
include Mongoid::Timestamps
#embeds_many :businesses, :class_name => "Business"
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :role_ids, :as => :admin
attr_accessible :username, :email, :password, :password_confirmation, :remember_me, :business_ids,
:reset_password_sent_at, :reset_password_within, :address, :city, :state, :zip, :country, :phone, :business_attributes
has_one :businesses
accepts_nested_attributes_for :businesses
validates_format_of :email, :with=>email_regexp, :allow_blank => true, :message=> "Justin"
#intercom
attr_accessor :company_name
attr_accessible :company_name
## Database authenticatable
field :email, :type => String, :default => ""
field :encrypted_password, :type => String, :default => ""
## Recoverable
field :reset_password_token, :type => String
#field :reset_password_sent_at, :type => Time
field :reset_password_sent_at, :type => Time
## Rememberable
field :remember_created_at, :type => Time
#field :remember_created_at, :type => String
## Trackable
field :username, :type => String
field :sign_in_count, :type => Integer, :default => 0
#field :current_sign_in_at, :type => Time
#field :last_sign_in_at, :type => Time
field :current_sign_in_at, :type => Time
field :last_sign_in_at, :type => Time
field :current_sign_in_ip, :type => String
field :last_sign_in_ip, :type => String
field :first_name, :type => String
field :last_name, :type => String
#field :business_ids, :type => Array
field :address, :type => String
field :city, :type => String
field :state, :type => String
field :zip, :type => String
field :country, :type => String
field :phone, :type => String
# User Avatar
attr_accessible :avatar
has_mongoid_attached_file :avatar,
:styles => { :full => ["512x512>", :jpg], :medium => ["256x256>", :jpg] },
:convert_options => {:medium => "-background black -gravity center -extent 256x256"},
:default_url => "/assets/avatar-blank.png"
validates_attachment_size :avatar, :less_than => 5.megabytes
validates_attachment_content_type :avatar, :content_type => ['image/jpeg', 'image/jpg', 'image/png', 'image/gif']
## Confirmable
# field :confirmation_token, :type => String
# field :confirmed_at, :type => Time
# field :confirmation_sent_at, :type => Time
# field :unconfirmed_email, :type => String # Only if using reconfirmable
## Lockable
# field :failed_attempts, :type => Integer, :default => 0 # Only if lock strategy is :failed_attempts
# field :unlock_token, :type => String # Only if unlock strategy is :email or :both
# field :locked_at, :type => Time
## Token authenticatable
# field :authentication_token, :type => String
after_create :create_business
def create_business
Business.create(business_id: self.id)
end
def assign_default_role(b)
# assign a default role if no role is assigned
# IF, invite token make user an editor for business
# ELSE, make the user owner of the business
self.add_role "owner", b
end
#Returns a businesses for a user. The return type is an array of Business models.
def businesses
Business.find(get_business_ids)
end
#returns the user business_ids (Array of Strings)
def get_business_ids
Business.find_roles(nil, self).map{|b| b.resource_id.to_s}.to_a
end
end
Try override Devise's registration controller:
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def create
# save business here
end
end
And then tell devise to use customized controller:
# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}

How to write a custom SimpleForm Builder to replace <INPUT> by <P>?

Extract of my Gemfile:
gem 'rails', '3.0.3'
gem 'inherited_resources', '1.2.1'
gem 'simple_form', '1.4.0'
For any resource, I have 1 view for the 3 actions (new, edit & show). Example:
<h1><%= I18n.t('admin.form.'+action_name.downcase, :name => controller_friendly_name) %></h1>
<%= simple_form_for([:admin, resource]) do |f| %>
<%= render "admin/shared/errors" %>
<%= f.input :title,
:label => "Title",
:hint => I18n.t('admin.form.input.title.hint', :name => controller_friendly_name),
:required => true,
:error => false,
:input_html => { :class => :large, :placeholder => I18n.t('admin.form.input.title.placeholder', :name => controller_friendly_name) }
%>
<%= f.input :is_visible,
:as => :radio,
:label => "Visible",
:error => false,
:required => true,
:collection => [['Yes', true], ['No', false]],
:wrapper_class => 'checkboxes-and-radiobuttons',
:checked => true
%>
<%= render "admin/shared/validation", :f => f %>
<% end %>
<% init_javascript "MyApplication.Form.disable();" if [:show].include?(action_name.to_sym) %>
See how the #show action set all the fields to disabled ? This is ugly.
Consider I can't refactor the views to have a show.html.erb file.
What I want to do:
When the action is #show, the simple_form builder use a custom builder wich replace <input>, <textarea>, <select> by <p> html tag, with the value.
Furthermore, I will customise the radiobuttons, checkboxes to.
My first step:
# app/inputs/showvalue_input.rb
class ShowvalueInput < SimpleForm::Inputs::Base
def input
# how to change 'text_field' by <p> container ?
#builder.text_field(attribute_name, input_html_options)
end
end
Can't find the way to do it. Custom Form Builders or Custom Inputs (with monkey patching) ?
Thank for the help !
Here's my solution
in my application_helper.rb:
def set_show_method_to_builder(builder)
builder.instance_eval <<-EVAL
def show?
#{action_name == "show"}
end
EVAL
end
In my forms (in the simple_form block):
<%- set_show_method_to_builder(f) -%>
And finally, in #app/inputs/string_input.rb:
class StringInput < SimpleForm::Inputs::StringInput
def input
if #builder.show?
content_tag(:p, #builder.object[attribute_name], :class => :show)
else
super
end
end
end
There's some problem with data types not mapped, but it's another story:
Can't create Custom inputs for some (Text, Booleans, ...) types, with SimpleForm

Resources