Rails doesn't receive http post request parameters - ruby-on-rails

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

Related

how to update user in ruby on rails

I am trying to update user info and i am having error that it didn't get any data from my form
Here is my user.controller:
def update
if !session[:id]
redirect_to '/users'
else
#user = User.find(params[:id])
#user.update(update_params)
if #user.valid?
#user.save
redirect_to '/events'
else
flash[:errors] = #user.errors.full_messages
redirect_to "/users/#{#user.id}/edit"
end
end
end
def update_params
params.require(:user).permit(:fname, :lname, :email, :city, :state)
end
edit update form
here is my edit.html.erb form:
<form action="/users/<%= #user.id %>/update" method="post">
<input type="hidden" name="_method" value="patch">
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
<div class="form-group row">
<label for="fname" class="col-sm-2 col-form-label">First Name</label>
<div class="col-sm-10">
<input type="text" name="user[fname]" class="form-control" placeholder="<%= #user.fname %>">
</div>
</div>
<div class="form-group row">
<label for="lname" class="col-sm-2 col-form-label">Last Name</label>
<div class="col-sm-10">
<input type="text" name="user[lname]" class="form-control" placeholder="<%= #user.lname %>">
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" name="user[email]" class="form-control" placeholder="<%= #user.email %>">
</div>
</div>
<div class="form-group row">
<label for="location" class="col-sm-2 col-form-label">Location</label>
<div class="col-sm-5">
<input type="text" name="user[city]" class="form-control" placeholder="<%= #user.city %>">
</div>
<div class="col-sm-5">
<select class="custom-select" name="user[state]">
<%= options_for_select(us_states)%>
</select>
</div>
</div>
<div class="form-group row clearfix">
<div class="col-sm-10 offset-sm-2">
<button type="submit" class="btn btn-primary float-right">Update</button>
</div>
</div>
</form>
Just updated my html form
this is error in terminal when i hit submit from my form:
(0.1ms) begin transaction User Exists (1.7ms) SELECT 1 AS one
FROM "users" WHERE ("users"."email" = 'nhan13574#gmail.com' AND
"users"."id" != 1) LIMIT 1 (0.1ms) rollback transaction Redirected
to http://localhost:4000/users/1/edit
Can you share the form? mostly the issue is there.
Also, #user.update actually saves the data in db, no need to save after it.. here is a refactored version of your snippet:
def update
return redirect_to '/users' unless session[:id]
#user = User.find(params[:id])
if #user.update(update_params)
redirect_to '/events'
else
flash[:errors] = #user.errors.full_messages
redirect_to "/users/#{#user.id}/edit"
end
end

Form validation in 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

trouble logging in to rails app after logout

This community looks great. I'm new to rails so please bear with some confusion. I have an app that lets a new user signup. The user gets created along with a wallet object that obtains a foreign key that matches the users given primary key. When I click logout, I return to the intended page, but all of a sudden, I am being thrown an "invalid combination" error... I feel like ever since I introduced the current_user helper method, that it's been throwing something off. Here are pieces of my files
The session's controller
class SessionsController < ApplicationController
skip_before_action :require_login, only: [:new, :create]
def new
end
def create
#user = User.find_by_email(params[:email])
if #user && #user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to "/users/#{#user.id}"
else
flash[:errors] = ["Invalid Combination"]
redirect_to "/sessions/new"
end
end
def destroy
session.delete(:user_id)
redirect_to "/sessions/new"
end
end
The user's controller
class UsersController < ApplicationController
skip_before_action :require_login, only: [:new, :create]
before_action :require_correct_user, only: [:edit, :show, :update, :destroy]
def new
end
def show
#user = User.includes(:wallet).find_by_id(params[:id])
end
def edit
end
def create
#user = User.create user_params
#wallet = Wallet.new
#wallet.save
#user.wallet_id = #wallet.id
#wallet.user = #user
if #user.save && #wallet.save
session[:user_id] = #user.id
redirect_to "/users/#{#user.id}"
else
flash[:errors] = #user.errors.full_messages + #wallet.errors.full_messages
redirect_to "/sessions/new"
end
end
private
def require_correct_user
if current_user != User.find(params[:id])
redirect_to "/users/#{session[:user_id]}"
end
end
def user_params
params.require(:user).permit(:email, :motto, :bio, :first_name,
:last_name,
:password, :password_confirmation)
end
end
And finally, here's the view I am directing to for both new signups and existing users login (sessions#new). Please let me know where you see any potential hiccups! Thanks!
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo center">
<%=image_tag("straightupLogoSiteHome.png")%></a>
<ul id="nav-mobile" class="left hide-on-med-and-down">
</ul>
<ul id="nav-mobile" class="right hide-on-med-and-down">
</ul>
<ul class="side-nav" id="mobile-demo">
</ul>
</div>
</nav>
<div class="container">
<br><br>
<div class="row">
<h3 class="center light">SIMPLE P2P BETTING</h3>
<br><br><br>
<div class="col s5 push-s7">
<H5 class="light">OR PLEASE... JOIN US</H5>
<form action="/users" method="post">
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
<div class="input-field col s12">
<input type="text" id="Email" name = "user[email]">
<label for="Email">EMAIL</label>
</div>
<div class="input-field col s12">
<input type="text" id="Motto" name = "user[motto]">
<label for="Motto">YOUR MOTTO (OPTIONAL)</label>
</div>
<div class="input-field col s12">
<input type="text" id="Bio" name = "user[bio]">
<label for="Bio">A BIO (OPTIONAL)</label>
</div>
<div class="input-field col s6">
<input type="text" id="First_Name" name = "user[first_name]">
<label for="First_Name">FIRST NAME</label>
</div>
<div class="input-field col s6">
<input type="text" id="Last_Name" name = "user[last_name]">
<label for="Last_Name">HOUSE NAME</label>
</div>
<div class="input-field col s6">
<input type="text" id="Password" name = "user[password]">
<label for="Password">PASSWORD</label>
</div>
<div class="input-field col s6">
<input type="text" id="Password_Confirmation" name = "user[password_confirmation]">
<label for="Password_Confirmation">AND AGAIN!</label>
</div>
<a class="waves-effect waves-light btn"><input type="submit" name="Join" value="JOIN US"></a>
</form>
</div>
<div class="col s4 pull-s4">
<H5 class="light">LOG BACK IN. sorry...</H5>
<form action="/sessions" method="post">
<input type="hidden" name="authenticity_token" value="<%=
form_authenticity_token %>">
<div class="input-field col s12">
<input type="text" id="Email" name = "user[email]">
<label for="Email">EMAIL</label>
</div>
<div class="input-field col s12">
<input type="text" id="Password" name = "user[password]">
<label for="Password">PASSWORD</label>
</div>
<a class="waves-effect waves-light btn"><input type="submit" name="login" value="Login"></a>
</form>
</div>
</div>
</div>
Aplogies. The current_user is defined in the applications_controller below. Thanks!
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
def authorize
redirect_to "/sessions/new" unless current_user
end
end
Ok. The issue was here... The answer I received was a bit of a workaround which is not at all what I need when I'm learning. So in my sessions_controller, I was defining a user by the params specified for the user in the users_controller. What I needed to do was define say login_params within the sessions_controller.. either that or in the create method .find_by_email(params[user.email]). I chose to create this private method at the bottom and changed the
.find_by_email(params[:email]) and the authenticate(params[:password])
to
.find_by_email(login_params[:email]) and the authenticate(login_params[:password])
private
def login_params
params.require(:user).permit(:email, :password)
end

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

Ruby on Rails param is missing or the value is empty without using a model

In my contact.html, I have this code
<div class="form">
<form name="email-form" method="POST">
<label class="field-label" for="name">Name:</label>
<input class="w-input text-field-2" id="name" type="text" name="name" data-name="Name" required="required">
<label class="field-label" for="Email">Email:</label>
<input class="w-input text-field-2" id="email" type="email" name="email" data-name="Email" required="required">
<label class="field-label" for="Subject">Subject:</label>
<input class="w-input text-field-2" id="subject" type="text" name="subject" data-name="Subject">
<label class="field-label" for="Content">Text Message:</label>
<textarea class="w-input text-field-2 area" id="content" name="content" data-name="Text Area" required="required"></textarea>
<div>
<input class="w-button button" type="submit" value="Submit Message" data-wait="Please wait...">
</div>
</form>
</div>
This is under my controller
def contact
end
def send_mail
MessageMailer.new_message(contact_params).deliver
redirect_to contact_path, notice: 'Your messages has been sent.'
end
private
def contact_params
params.require(:contact).permit(:name, :email, :subject, :content)
end
under mailers/message_mailer.rb
class MessageMailer < ActionMailer::Base
default from: "sys.questdentalusa#gmail.com"
default to: "questdentalusa#gmail.com"
def new_message(contact)
#contact = contact
mail subject: #contact.subject
end
end
and under my new_message.text.erb is this code
Name: <%= #contact.name %>
Email: <%= #contact.email %>
Message: <%= #contact.content %>
I am to send an email consisting user's name, email and message which is inputed and NOT saved in the database. When I pass the four parameters like this
def send_mail
MessageMailer.new_message(:name, :email, :subject, :content).deliver
redirect_to contact_path, notice: 'Your messages has been sent.'
end
it worked just fine but i was told to use only one parameter, seems like group the four parameters: name, email, subject, content as one (contact)
When I typed the info and hit the submit button, I get this error message
param is missing or the value is empty: contact
I presume that what caused this error is because my def contact is empty. So I added contact.new and #contact=contact.new and MessageMailer.new but this error occurs NoMethodError
How can I possibly fix this? What should I write under my def contact ?
Your controller code is correct. You don't need Contact.new or something. The problem is with your <form>. What ends up in params depends on your form and in your form you don't have contact.
Instead of:
<input type="text" name="subject">
You have to do something like this:
<input type="text" name="contact[subject]">
And that for all the fields on your contact form.
Another option would be to use Rails' form helpers.
contact[] is missing in your form, see below correct one:
<div class="form">
<form name="email-form" method="POST">
<label class="field-label" for="name">Name:</label>
<input class="w-input text-field-2" id="name" type="text" name="contact[name]" data-name="Name" required="required">
<label class="field-label" for="Email">Email:</label>
<input class="w-input text-field-2" id="email" type="email" name="contact[email]" data-name="Email" required="required">
<label class="field-label" for="Subject">Subject:</label>
<input class="w-input text-field-2" id="subject" type="text" name="contact[subject]" data-name="Subject">
<label class="field-label" for="Content">Text Message:</label>
<textarea class="w-input text-field-2 area" id="content" name="contact[content]" data-name="Text Area" required="required"></textarea>
<div>
<input class="w-button button" type="submit" value="Submit Message" data-wait="Please wait...">
</div>
</form>
</div>

Resources