I am new, so I apologize in advance if there is some issues with my explanation of my issue, I am using Ionic v1. on the frontend and this ruby tutorial for the backend: https://www.simplify.ba/articles/2016/06/18/creating-rails5-api-only-application-following-jsonapi-specification/.
I am trying to create a user and have that information stored in the backend, but continue to run into a 422 (Unprocessable Entity Error). I have read many different forums, but am stuck.
Here's my front end:
.controller('SignupCtrl', function($scope,SignupSession,$ionicPopup) {
$scope.signup = function(full_name, password, repeat_password) {
var user_session = new SignupSession({ user: { full_name: full_name, password: password }});
user_session.$save(
function(data){
window.localStorage['full_name'] = full_name;
window.localStorage['password'] = password;
$location.path('/app/playlists');
},
function(err){
$ionicPopup.alert({
title: 'An error occured',
template: err["data"]["error"]
});
}
);
}
})
.factory('SignupSession', function($resource) {
return $resource(window.server_url + "/users.json") //application/vnd.api+json
})
Here's my backend:
User Controller:
def create
user = User.new(user_params)
if user.save
render json: user, status: :created, meta: default_meta
else
render_error(user, :unprocessable_entity)
end
end
def user_params
ActiveModelSerializers::Deserialization.jsonapi_parse(params)
end
Sessions Controller:
def create
data = ActiveModelSerializers::Deserialization.jsonapi_parse(params)
Rails.logger.error params.to_yaml
user = User.where(full_name: data[:full_name]).first
head 406 and return unless user
if user.authenticate(data[:password])
user.regenerate_token
render json: user, status: :created, meta: default_meta,
serializer: ActiveModel::Serializer::SessionSerializer and return
end
Here's my log and info from Google Chrome:
Started POST "/users.json" for 127.0.0.1 at 2017-08-04 12:40:39 -0700
Processing by UsersController#create as JSON
Parameters: {"user"=>{"full_name"=>"btejes#yahoo.com", "password"=>"[FILTERED]"}}
[1m[35m (0.1ms)[0m [1m[36mbegin transaction[0m
[1m[35m (0.1ms)[0m [1m[31mrollback transaction[0m
[active_model_serializers] Rendered ActiveModel::Serializer::ErrorSerializer with ActiveModelSerializers::Adapter::JsonApi (0.29ms)
Completed 422 Unprocessable Entity in 6ms (Views: 0.7ms | ActiveRecord: 0.2ms)
{errors: [{source: {pointer: "/data/attributes/password"}, detail: "can't be blank"},…]}
errors
:
[{source: {pointer: "/data/attributes/password"}, detail: "can't be blank"},…]
Does it have something to do with the content type needing to have, "application/vnd.api+json" in the front end? Any help would be greatly appreciated, and I apologize in advance that this post is on the longer side.
Ben
Related
Through the terminal I can make the CRUD Syllabus, but when I do it through my program's interface it doesn't allow me to "create" and does the ROLLBACK. How to debug this? I've tried it in so many ways, I don't know exactly what's going on. The strangest thing is that I've always managed to do this through the terminal.
my controller
before_action :set_syllabus, only: [:show, :update, :destroy]
def show
if #syllabus
scheduled_dates = JSON.parse #syllabus.scheduled_dates
# interests_array = #syllabus.student_interests.pluck(:data)
if current_student.status != "freemium"
render json: {
goal: #syllabus.goal,
objective: #syllabus.objective,
level: #syllabus.level,
estimate: #syllabus.estimate,
interests: #syllabus.interests,
skills: #syllabus.skills,
schedule: {
dates: scheduled_dates,
minutes: #syllabus.scheduled_minutes
}
# }.merge({:interests => interests_array })
}
else
render json: {
blocked: true,
goal: #syllabus.goal,
objective: #syllabus.objective,
level: #syllabus.level,
estimate: #syllabus.estimate,
interests: #syllabus.interests,
skills: #syllabus.skills,
schedule: {
dates: scheduled_dates,
minutes: #syllabus.scheduled_minutes
}
# }.merge({:interests => interests_array })
}
end
else
render json: {
errors: "Record not found."
}, status: 404
end
end
def create
#syllabus = Syllabus.new(syllabus_params)
if #syllabus.save
render json: #syllabus.as_json, status: :created
else
render json: {
errors: #syllabus.errors
}, status: :unprocessable_entity
end
end
def update
if #syllabus.update(syllabus_params)
render json: #syllabus.as_json(except: [:id]), status: :ok
else
render json: {
errors: #syllabus.errors
}, status: :unprocessable_entity
end
end
def destroy
if #syllabus.destroy
render :no_content
else
render json: { errors:
breweries.errors.full_messages
}, status: :unprocessable_entity
end
end
private
def set_syllabus
#syllabus = Syllabus.find_by(student_id: params[:id])
end
def syllabus_params
params.permit(
:student_id,
:objective,
:level,
:goal,
:estimate,
:interests,
:skills,
:scheduled_dates,
:scheduled_minutes
)
end
end```
```[619aec90-7658-4825-aebb-82fc7aecc978] Started POST "/api/v1/students/syllabus" for ::1 to 2021-08-05 14:35:52 -0300
[619aec90-7658-4825-aebb-82fc7aecc978] Processing by Api::V1::SyllabusController#create as HTML
[619aec90-7658-4825-aebb-82fc7aecc978] Parameters: {"student_id"=>52776, "level"=>"Basic", "objective"=>"Be able to travel more smoothly", "goal"=>"Advanced ", "estimate"=>14.625, "scheduled_dates"=>["dom", "sab"], "scheduled_minutes"=>200, "interests"=>["Sports", ""], "syllabus"=> {"student_id"=>52776, "objective"=>"Be able to travel more smoothly", "level"=>"Basic", "goal"=>"Advanced", "estimate"=>14.625, "scheduled_dates"= >["dom", "sat"], "scheduled_minutes"=>200, "interests"=>["Sports", ""]}}
[619aec90-7658-4825-aebb-82fc7aecc978] Unpermitted parameters: :scheduled_dates, :interests, :syllabus
[619aec90-7658-4825-aebb-82fc7aecc978] (0.4ms) BEGIN
[619aec90-7658-4825-aebb-82fc7aecc978] ↳ app/controllers/api/v1/syllabus_controller.rb:49
[619aec90-7658-4825-aebb-82fc7aecc978] Student Load (0.5ms) SELECT "students".* FROM "students" WHERE "students"."id" = $1 LIMIT $2 [["id", 52776], [" LIMIT", 1]]
[619aec90-7658-4825-aebb-82fc7aecc978] ↳ app/controllers/api/v1/syllabus_controller.rb:49
[619aec90-7658-4825-aebb-82fc7aecc978] (0.2ms) ROLLBACK
[619aec90-7658-4825-aebb-82fc7aecc978] ↳ app/controllers/api/v1/syllabus_controller.rb:49
[619aec90-7658-4825-aebb-82fc7aecc978] Completed 422 Unprocessable Entity in 541ms (Views: 0.1ms | ActiveRecord: 5.2ms)```
The error is right there, unpermitted parameters.
You will need to add require(:syllabus) to your strong parameters.
params.require(:syllabus).permit(
:student_id,
:objective,
:level,
:goal,
:estimate,
:skills,
:scheduled_minutes
interests: [],
scheduled_dates: [],
)
My app is using Rails for the API and React for the client. My attempts to create a resource are failing. I want to get one value (description) from the user and provide defaults for the rest.
Here's the server log:
Started POST "/api/v1/goals" for ::1 at 2020-09-21 07:05:13 -0700
Processing by Api::V1::GoalsController#create as HTML
Parameters: {"goal"=>{"description"=>"Leggo"}}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."uid" = $1 LIMIT $2 [["uid", "fake#email.com"], ["LIMIT", 1]]
Completed 500 Internal Server Error in 66ms (ActiveRecord: 0.6ms | Allocations: 14791)
RuntimeError (<ActionController::Parameters {"goal"=>{"description"=>"Leggo"}, "controller"=>"api/v1/goals", "action"=>"create"} permitted: false>):
app/controllers/api/v1/goals_controller.rb:52:in `goal_params'
app/controllers/api/v1/goals_controller.rb:19:in `create'
The controller action:
def create
#goal = Goal.new(goal_params, user_id: current_user.id, complete: false, category_id: 1)
if #goal.save
render json: #goal, status: :created, location: #goal
else
render json: #goal.errors, status: :unprocessable_entity
end
end
The strong params method:
def goal_params
raise params.inspect
params.fetch(:goal).permit(:description)
end
And the client-side request:
try {
await axios({
method: 'post',
url,
headers,
data: { goal: { description } }
});
console.log('Created goal');
setDescription('');
} catch (err) {
console.log(err);
}
Remove the raise params.inspect firstly.
If you're getting a 422 Unprocessable Entity response that means #goal.save isn't working - likely because of a validation requirement on your Goal model? Print #goal.errors in your console before you save it if you want to see exactly why.
I have a rails 6 API (Backend) running a Vue & Flutter Frontend,
When I try to pass my user credentials to the API from Vue I am getting the following error:
app/controllers/signin_controller.rb:6:in `create'
Started POST "/signin" for ::1 at 2019-11-13 02:51:58 -0700
Processing by SigninController#create as HTML
Parameters: {"user"=>{"email"=>"xxxxxx#xxxxxx.co", "password"=>"[FILTERED]"}}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."email" IS NULL LIMIT $1 [["LIMIT", 1]]
↳ app/controllers/signin_controller.rb:5:in `create'
Completed 404 Not Found in 6ms (ActiveRecord: 2.1ms | Allocations: 3220)
ActiveRecord::RecordNotFound (Couldn't find User):
app/controllers/signin_controller.rb:5:in `create'
now I can go into my rails console and the User dose exist with the MATCHING email address.
I am not too sure what to do to get this user found and signed in.
I am using JWT Sessions to handle the tokens and axios to make the calls to the api.
here is my signin controller create action.
def create
user = User.find_by!(email: params[:email])
if user.authenticate(params[:password])
payload = { user_id: user.id }
session = JWTSessions::Session.new(payload: payload, refresh_by_access_allowed: true)
tokens = session.login
response.set_cookie(JWTSessions.access_cookie,
value: tokens[:access],
httponly: true,
secure: Rails.env.production?)
render json: { csrf: tokens[:csrf] }
else
not_authorized
end
end
and here is the full method I am sending from vue:
signin () {
let formData = new FormData()
formData.append('user[email]', this.user.email)
formData.append('user[password]', this.user.password)
this.$http.plain.post('/signin', formData, {emulateJSON: true})
.then(response => this.signinSuccessful(response))
.catch(error => this.signinFailed(error))
},
signinSuccessful (response) {
if (!response.data.csrf) {
this.signinFailed(response)
return
}
localStorage.csrf = response.data.csrf
localStorage.signedIn = true
this.$router.replace('/dashboard')
},
signinFailed (error) {
this.error = (error.response && error.response.data && error.response.data.error) || ''
delete localStorage.csrf
delete localStorage.signedIn
},
checkSignedIn () {
if (localStorage.signedIn) {
this.$router.replace('/dashboard')
}
}
}
Any assistance here would be greatly appreciated! Thanks in advance!
From the request log we can see that the parameters coming in to your controller are:
Parameters: {"user"=>{"email"=>"xxxxxx#xxxxxx.co", "password"=>"[FILTERED]"}}
We can also see query that is made to the database:
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."email" IS NULL LIMIT $1 [["LIMIT", 1]]
Especially
WHERE "users"."email" IS NULL
So the email you're passing into the query is nil.
You should find the user like this instead
User.find_by!(email: params[:user][:email])
Or preferably
def create
user = User.find_by!(email: user_params[:email])
...
end
def user_params
params.require(:user).permit(:email, :password)
end
So I have a Participant model created in Rails API Mode.
This is what the controller of that looks like :
class ParticipantsController < ApplicationController
acts_as_token_authentication_handler_for User
def create
binding.pry
participant = Participant.new(participant_params)
puts "INFO: ----------------------------"
puts participant.inspect
puts params
if(participant.save)
render json: {
status: 'SUCCESS',
message: 'Participant link created',
data: participant
}, status: :created
else
render json: {
status: 'ERROR',
message: 'Participant link not created',
data: participant.errors
}, status: :unprocessable_entity
end
end
private def participant_params
params.permit(:id_request, :user_id)
end
end
Here is the User model :
class User < ApplicationRecord
acts_as_token_authenticatable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :firstname, presence: true
validates :lastname, presence: true
validates :username, presence: true
validates :address, presence: true
validates :idcard, presence: true
end
The second line you will see this : acts_as_token_authentication_handler_for User
This allows me to add authentication headers in my fetch request in React.
This is how I fetch it :
participateToContribution = id_request => {
const data = {
id_request: id_request,
user_id: localStorage.getItem('email')
}
console.log(data)
fetch('http://localhost:3000/participants', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-User-Email': localStorage.getItem('email'),
'X-User-Token': localStorage.getItem('token')
},
data: data
})
}
I've done this with other controllers and it works well, but now for some reasons when I fetch this rails returns me this error :
Started POST "/participants" for 127.0.0.1 at 2019-07-11 19:08:36 +0200
Processing by ParticipantsController#create as */*
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? ORDER BY "users"."id" ASC LIMIT ? [["email", "titivermeesch#gmail.com"], ["LIMIT", 1]]
↳ /home/tristan/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Unpermitted parameters: :user_email, :user_token
(0.2ms) begin transaction
↳ app/controllers/participants_controller.rb:7
(0.2ms) rollback transaction
↳ app/controllers/participants_controller.rb:7
Completed 422 Unprocessable Entity in 11ms (Views: 0.4ms | ActiveRecord: 0.7ms)
I tried to add those 2 fields in the .permit() but this gives me another error (I didn't have any of this in my other controllers, and it's just copy pasted).
Started POST "/participants" for 127.0.0.1 at 2019-07-11 19:13:15 +0200
(0.5ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
↳ /home/tristan/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Processing by ParticipantsController#create as */*
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? ORDER BY "users"."id" ASC LIMIT ? [["email", "titivermeesch#gmail.com"], ["LIMIT", 1]]
↳ /home/tristan/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Completed 500 Internal Server Error in 56ms (ActiveRecord: 3.3ms)
ActiveModel::UnknownAttributeError (unknown attribute 'user_email' for Participant.):
app/controllers/participants_controller.rb:5:in `create'
This is what is sent to this controller from the front-end part :
{id_request: 1, user_id: "titivermeesch#gmail.com"}
The GitHub code : https://github.com/titivermeesch/neighbourhood-app
pry output :
4: def create
=> 5: binding.pry
6: participant = Participant.new(participant_params)
7: puts "INFO: ----------------------------"
8: puts participant.inspect
9: puts params
10: if(participant.save)
11: render json: {
12: status: 'SUCCESS',
13: message: 'Participant link created',
14: data: participant
15: }, status: :created
16: else
17: render json: {
18: status: 'ERROR',
19: message: 'Participant link not created',
20: data: participant.errors
21: }, status: :unprocessable_entity
22: end
23: end
Update fetch with
fetch('http://localhost:3000/participants', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-User-Email': localStorage.getItem('email'),
'X-User-Token': localStorage.getItem('token')
},
body: JSON.stringify({data)
})
}
and data with
const data = {
participant: {
id_request: id_request,
user_id: localStorage.getItem('email')
}
}
and participant_params as
def participants_params
params.require(:participant).permit(:id_request, :user_id)
end
In this case, you should add those fields (email and token) to your User class. Here we have a complete example for https://gist.github.com/bosskovic/816623404b60b30726a8
Case you already have these fields, you just have to map user_email param to email column properly.
You are not permitting them here
private
def participants_params
params.permit(:id_request, :user_id)
end
You have to add them to that array like this
private
def participants_params
params.permit(:id_request, :user_id, :user_email, :user_token)
end
Now you said that that threw an error, because user_email is not a field on participant. You will need to add it in order to save a value to it, otherwise you need to take it out of the parameter array getting sent, and then the object will save. You can't send unpermitted paramters and try to save it, it just won't work.
The only other solution is to re write you create method, but this is not really a solution.
def create
participant = Participant.new
participant.request_id = params[:participant][:id_request]
participant.user_id = params[:participant][:user_id]
if(participant.save)
...
I want use rails 4 as a server and post data to rails and then data is save to database. For this, I sen data by http and update method. But when data recieve in server and rails want to save data, I get Unpermitted parameters: id error. I post data by below code:
$scope.updateRadif = function(index, ID){
console.log(ID);
RadifSecure.update(index, {bolouk_id: 1, id: ID}).$promise.then(function(data){
//...
})
.catch(function (err) {
//...
})
};
app.factory('RadifSecure', function($resource) {
return $resource("/api/bolouks/:bolouk_id/radifs/:id", { bolouk_id: '#bolouk_id', id: "#id" },
{
'show': { method: 'GET', isArray: false },
'update': { method: 'PUT' },
'destroy': { method: 'DELETE' }
}
);
});
and I recieve data in rails server:
def update
#radif = Radif.find(params[:id])
respond_to do |format|
if #radif.update_attributes(radif_params)
format.json { head :no_content }
else
format.json { render json: #radif.errors, status: :unprocessable_entity }
end
end
end
private
def radif_params
params.require(:radif).permit(:bolouk_id, :describe, :price)
end
When I check the server log, the data is recieve ccorrectly, but rails doesn't permit to save in database:
Started PUT "/api/bolouks/1/radifs/16?describe=sdsad&price=3423432" for 127.0.0.1 at 2014-09-03 11:14:27 +0430
Processing by Api::V1::RadifsController#update as JSON
Parameters: {"bolouk_id"=>"1", "id"=>"16", "describe"=>"sdsad", "price"=>"3423432", "radif"=>{"id"=>"16", "bolouk_id"=>"1"}}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 7 ORDER BY "users"."id" ASC LIMIT 1
Radif Load (0.0ms) SELECT "radifs".* FROM "radifs" WHERE "radifs"."id" = ? LIMIT 1 [["id", 16]]
Unpermitted parameters: id
(0.0ms) begin transaction
(0.0ms) commit transaction
Completed 204 No Content in 29ms (ActiveRecord: 0.0ms)
I try other code to solve this problem, but I'm not successful.
def update
#radif = Radif.find(params[:id])
radif.update!(radif_params)
end
Any one can help me to solve this problem?