Form validation in ruby on rails - ruby-on-rails

I have built a sign up page in ruby on rails. I want to validate this sign up form. For example - if user left any section blank, the form will show an error message. It will also check whether the given email is unique. How can I do this by not changing my form?
#This my logins_controller.rb file
class LoginsController < ApplicationController
skip_before_action :verify_authenticity_token
def index
#subscriber=Subscriber.new()
end
def sign_up
subscriberNew = Subscriber.new
subscriberNew.name = params[:name]
subscriberNew.cus_user_name = params[:user_name]
subscriberNew.cus_password = params[:password]
subscriberNew.cus_email = params[:email]
result = subscriberNew.save
respond_to do |format|
msg = { :status => "ok", :message => "Success!" }
format.json { render :json => msg }
end
end
def validate_signup
#what should i write here?
end
end
and this is my sign up form
<div class="container">
<div class="shadow-lg p-3 mb-5 bg-white rounded view-card">
<h4 class="card-title">
<a href="/product_types">
<i class="material-icons">
arrow_back_ios
</i></a></h4>
<form id="signup_form" method="post" action="/sign-up">
<p class="h4 mb-4">Register to Binimoy</p>
<label for="name">Name</label>
<input type="text" name="name" id="name" class="form-control mb-4" placeholder="Name">
<label for="email">Email</label>
<input type="email" name="email" id="email" class="form-control mb-4" placeholder="Email">
<label for="phone">Phone</label>
<input type="text" name="phone" id="phone" class="form-control mb-4" placeholder="Phone">
<label for="name">Password</label>
<input type="password" name="password" id="password" class="form-control mb-4" placeholder="Password">
<div class="form-row mb-4">
<div class="col">
<button class="btn btn-default my-4 btn-block" type="reset">Reset</button>
</div>
<div class="col">
<button type="button" class="btn btn-info my-4 btn-block" id="submitAnchor">Submit</button>
</div>
</div>
</form>
</div>

First, use Rails helpers in your views and write your form as documented here.
<%= form_with url: sign_up_path do |form| %>
<%= form.label :email %>
<%= form.text_field :email %>
...
<%= form.submit %>
<% end %>
Second, use validations in your Subscriber model as documented here.
validates :email, presence: true, uniqueness: true
...
Hope it helps ;)

Rails is an framework with an strong opinion how to do things. You are doing things not the Rails way and this will make it more complicated.
If you really do not want to change your form (which is strongly advice against)
Add validations, check the return value of save and send back some error message
In your model:
validates :email, presence: true, uniqueness: true
In your controller:
if subscriber.save
render json: {status: "ok", message: "success"}
else
render json: {status: "nok", message: "something went wrong"}
end
Probably you should get rid of the status property and use the HTTP status code for this (sending back 201 (created) and 422 (unprocessble entity) responses instead)
Some other recommendatations to make your code more readable:
Follow the Rails conventions (use a form builder, it simplifies the assignment of form params to the model
Use Ruby naming conventions:
subscriberNew
should be
subscriber_new
since Ruby uses camel_case
but actually there is no need for the new suffix, so subscriber is enough
Use two spaces for identation
Don't abbreviate variables (cus_username, ...) and don't prefix when there is no need

Related

Trying to render value of input field

Trying to work with a input value present in the source code only when the user has tried to login once (and entered a wrong password).
The scenario is as follows:
First attempt before login, part of the code looks like this:
<div class="form-group">
<label class="control-label col-md-4" for="user_email">Email</label>
<div class="col-md-8">
<input class="text-field form-control" html="{:spellcheck=>"false"}" id="user_email" name="user[email]" type="email" value="" />
</div>
</div>
After a second attempt happens, the email address that was used it's rendered in value:
<div class="form-group">
<label class="control-label col-md-4" for="user_email">Email</label>
<div class="col-md-8">
<input class="text-field form-control" html="{:spellcheck=>"false"}" id="user_email" name="user[email]" type="email" value="heregoestheemail#gmail.com" />
</div>
</div>
How can I render that email address if the user is not logged in yet? I know that once logged I'd do something like <%= current_user.email %> but there is way to get that value attribute?
you should work with form_for
<%= form_for #user do |f| %>
<% f.text_field :email (not sure f.email_field works)
<%= end %>
be sure #user is define in controller (#user = User.new or #user is come back from controller with errors => show #user.errors and contain precedent values)
http://guides.rubyonrails.org/form_helpers.html

Unauthorize error on password update Devise

I'm working on a rails api and using devise_token_auth for the authentication, when I try to update password by hitting the /auth/password with put request it responsds with error 401 i.e. unauthorized. My server logs show me this
Started PUT "/auth/password" Processing by
DeviseTokenAuth::PasswordsController#update as HTML Parameters:
{"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}
Can't verify CSRF token authenticity Completed 401 Unauthorized in
routes.rb
mount_devise_token_auth_for 'User', at: 'auth' ,:controllers => { :omniauth_callbacks => 'omniauth' }
view.html (angularjs)
<div class="container">
<div class="row">
<div class="row">
<div class="col-xs-6 col-xs-offset-3 que">
<img src="./uploads/img/web-logo.png" class="img-responsive" alt="Logo">
</div>
</div>
<div class="col-xs-12 reset-pas">
<form name="update_pass" ng-submit="updatePassword_controller()" role="form" class="lost_reset_password">
<p class="error_msg" ng-show="update_pass.password_confirmation.$error.passwordVerify">
Passwords are not equal!
</p>
<label>New password</label>
<input type="password" name="password" ng-minlength="8" ng-model="updatePasswordForm.password" required="required" class="form-control">
<span>Minimum 8 Charachters</span>
<br>
<label>Re-enter new password</label>
<input type="password" name="password_confirmation" ng-minlength="8" ng-model="updatePasswordForm.password_confirmation" required="required" class="form-control" password-verify="updatePasswordForm.password" >
<button type="submit" class="btn btn-default" id="reset-submit">Save</button>
</form>
</div>
</div>
</div>
controller.js
$scope.updatePassword_controller = function() {
$auth.updatePassword($scope.updatePasswordForm)
.then(function(resp) {
console.log(resp)
$location.path('/')
})
.catch(function(resp) {
console.log(resp)
});
};
Update
Note
I'm facing this issue only for password update
Update
I installed gem 'angular_rails_csrf' Now it's giving only the authorization error not the csrf attack error
Use the Rails form_tag or form_for helpers. They add will add a hidden field for the XCSRF token:
<div class="container">
<div class="row">
<div class="row">
<div class="col-xs-6 col-xs-offset-3 que">
<img src="./uploads/img/web-logo.png" class="img-responsive" alt="Logo">
</div>
</div>
<div class="col-xs-12 reset-pas">
<%= form_tag "#", { "ng-submit" => "updatePassword_controller()", "role" => "form", "class" => "lost_reset_password"} do %>
<p class="error_msg" ng-show="update_pass.password_confirmation.$error.passwordVerify">
Passwords are not equal!
</p>
<label>New password</label>
<input type="password" name="password" ng-minlength="8" ng-model="updatePasswordForm.password" required="required" class="form-control">
<span>Minimum 8 Charachters</span>
<br>
<label>Re-enter new password</label>
<input type="password" name="password_confirmation" ng-minlength="8" ng-model="updatePasswordForm.password_confirmation" required="required" class="form-control" password-verify="updatePasswordForm.password" >
<button type="submit" class="btn btn-default" id="reset-submit">Save</button>
</form>
</div>
</div>
</div>
I simply made a condition in applicationcontroller.rb like below and it worked out . The main idea is simply to override the functionality of Devise
if params[:controller] == "devise_token_auth/passwords" && params[:action] == "update"
uri = URI.parse(request.headers.env['HTTP_REFERER'])
query_params = CGI.parse(uri.query)
email = query_params['uid'].first
user = User.find_by_email(email)
user.password = params[:password]
user.password_confirmation = params[:password_confirmation]
if user.save
render json: {message: 'Password Updated successfully', status: 200}
else
render json: {message: 'Password Could not changed , Please contact to support Team', status: 401}
end
end
Although it's not the proper solution but i couldn't think of anyother one . So please bear with me .In it we're fetching email from url

Rails doesn't receive http post request parameters

I'm working on a simple one-page website on Ruby on Rails that has a 'Contact Us' form. It has 3 fields - name, e-mail and text -, and a submit button. In theory, after filling up these forms and clicking the button, the user will receive an email with the confirmation of the request. The controller basically has only one method that writes the data in the DB and after successful saving sends an email.
The problem is that the controller doesn't receive the parameters(name, email and text) and raises an exception: ActionController::ParameterMissing (param is missing or the value is empty: application)
I'm sure that the data is sent. Here's the log:
Started POST "/" for 127.0.0.1 at 2015-07-23 20:25:08 +0300
Processing by ApplicationsController#create as HTML
Parameters: {"name"=>"Foo Bar", "email"=>"foobar#example.com", "text"=>"qwerqwepoiqtwporihtqwojbr[sdfzxc"}
Completed 400 Bad Request in 381609ms
Source code of the controller:
class ApplicationsController < ApplicationController
skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'text/html' }
def new
#request = Application.new
end
def create
#request = Application.new(application_params)
if #request.save
ApplicationMailer.request_confirmation(#request).deliver_now
flash[:info] = 'Your application has been registered! Check your e-mail!'
else
flash[:alert] = 'Oops! Your application was not registered!'
end
end
private
def application_params
params.require(:application).permit(:name, :email, :text)
end
end
Source code of the Application model:
class Application < ActiveRecord::Base
before_save{
self.email.downcase!
}
validates(:name, presence: true, length: { maximum: 50 })
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates(:email, presence: true, length: {maximum: 255},
format: {with: VALID_EMAIL_REGEX})
validates(:text, presence: true)
end
Does anybody have any idea where is the problem and how to solve it?
Thank you in advance.
UPD:
Form code:
<form method="post" class="form-horizontal col-md-8" name="application" id="applyForm">
<div class="row" id="credentials">
<div class="col-sm-6">
<div class="input-group form-group" id="full_name">
<span class="input-group-addon" id="basic-addon1"><i class="fa fa-user"></i></span>
<input type="text" name="name" class="form-control" placeholder="Your name" aria-describedby="basic-addon1" id="name">
</div>
</div>
<div class="col-sm-6">
<div class="input-group form-group" id="email">
<span class="input-group-addon" id="basic-addon1"><i class="fa fa-envelope"></i></span>
<input type="text" name="email" class="form-control" placeholder="E-mail" aria-describedby="basic-addon1" id="email">
</div>
</div>
</div>
<div class="row" id="comment-area">
<div class="col-sm-12" id="comment">
<textarea class="form-control" name="text" rows="10" placeholder="Please describe your system" id="text"></textarea>
</div>
</div>
<div class="row" id="submit-button">
<button type="submit" class="btn btn-default"><i class="fa fa-rocket"></i>Send message</button>
</div>
</form>
Your params are not coming from application, for a quick fix just change application_params to below
def application_params
params.permit(:name, :email, :text)
end

Make all input fields on the same line

Im trying to use css to make all the fields for my form display on one line. It's part of the header nav on my page so it is important that it shows on one line instead of multiple lines.
Here's my header code at the moment.
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-target=".nav-collapse" data-toggle="collapse">
<span class="i-bar"></span>
<span class="i-bar"></span>
<span class="i-bar"></span>
</a>
<a class="brand" href="/">Bandini</a>
<div class="container nav-collapse">
<ul class="nav">
<li><%= link_to "Clients", "/clients" %></li>
<li><%= link_to "Jobs", "/jobs" %></li>
</ul>
<ul class="user_nav">
<%= render :partial => "sessions/manager" %>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
The <%= render :partial => "sessions/manager" %> part points to a partial which displayes another partial depending on the users login state.
If they are logged out, then it displays the login form and if they are logged in then it shows th currrent users email adress and a signout link.
Here's my login form.
<%= simple_form_for("user", :url => user_session_path, :html => {:id => "sign_in", :class => 'form-inline' }, :remote => true, :format => :json) do |f| %>
<%= f.input :email, :placeholder => 'Email' %>
<%= f.input :password, :placeholder => 'Password' %>
<%= f.submit 'Login' %>
<%= link_to "Forgot your password?", new_password_path('user') %>
<% end %>
The form utilizes ajax and the simple_form gem for all the markup.
Ive tried playing around in Googles element tools and adding display: inline; to all of my input fields but no such luck.
Can anyone assist or point me in the right direction?
Edit: HTML generated..
<ul class="user_nav">
<form accept-charset="UTF-8" action="/users/sign_in" class="simple_form form-inline" data-remote="true" id="sign_in" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="fN0oKIlpnhS0WLZpKQafln+182IT1ONVuDP0eRtT8fg=" /></div>
<div class="control-group email required"><label class="email required control-label" for="user_email"><abbr title="required">*</abbr> Email</label><div class="controls"><input class="string email required" id="user_email" name="user[email]" placeholder="Email" size="50" type="email" /></div></div>
<div class="control-group password required"><label class="password required control-label" for="user_password"><abbr title="required">*</abbr> Password</label><div class="controls"><input class="password required" id="user_password" name="user[password]" placeholder="Password" size="50" type="password" /></div></div>
<input name="commit" type="submit" value="Login" />
Forgot your password?
</form>
</ul>
The reason display: inline; on your inputs is not working is because simple_form by default wraps a div tag around every input. There are two ways to fix this problem:
Create a custom wrapper for simple_form
https://github.com/plataformatec/simple_form#the-wrappers-api
Set both your inputs and the surrounding div to be inline-block:
.user_nav div, .user_nav input, .user_nav input[type="submit"] {
display: inline-block;
}
While the .user_nav input css style theoretically should not be necessary, it helps to specify it just in case there is some other CSS rule somewhere setting inputs to block. If you're sure that inputs are behaving normally, then you should be able to remove the second part of the CSS definition above.
By what documentation says http://twitter.github.com/bootstrap/components.html#navbar
Just add navbar-form class to your form and pull-left or pull-right
Also you should place it inside a li tag since you are placing it inside a ul

Is there any way to create a form with formtastic without a model?

I would like to use formtastic to create form but I don't have a model associated with that (login form with username, password and openid URL).
Of course I could create a model to do that but that model was just a hack without any useful code in it.
You can pass a string instead of a model, which will be used to generate the field names:
<% semantic_form_for 'user', :url => 'login' do |f| %>
<% f.inputs :name => 'Login Details' do %>
<%= f.input :username %>
<%= f.input :password %>
<% end %>
<% end %>
Which will produce something like:
<form action="/login" class="formtastic user" method="post"><div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="E/NksKRd7Twh4nGp1Qc8jBQNfqYDn8gg6sWdTdCtl+g=" /></div>
<fieldset class="inputs"><legend><span>Login Details</span></legend><ol>
<li class="string required" id="user_username_input"><label for="user_username">Username<abbr title="required">*</abbr></label><input id="user_username" name="user[username]" size="50" type="text" /></li>
<li class="password required" id="user_password_input"><label for="user_password">Password<abbr title="required">*</abbr></label><input id="user_password" name="user[password]" size="50" type="password" /></li>
</ol></fieldset>
</form>
But you will need to be more specific with your options as formtastic won't be able to work out what types of fields it should use, all will default to textfields (although it automatically makes fields named like password password type fields).
A better way to do this though would be with a sessions model, have a look at the way authlogic (http://github.com/binarylogic/authlogic) works for more info.

Resources