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)
...
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: [],
)
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
In javascript I do an ajax call to the create function of deliveries_controller. This puts a new Delivery in the database with a product and quantity. I also try to put the current_user as user_id in the database, but for some reason it stays nil in the database.
My ajax call:
$.ajax({
type: "POST",
url: "/deliveries",
data: { delivery: {ingredient: "meel", quantity: "800", scenario_id: "3"} },
success: function(){
alert('Success!');
},
error: function(){
alert('No success');
}
});
I just pass some dummy data to test it all out.
and my deliveries_controller:
class DeliveriesController < ApplicationController
protect_from_forgery
def index
#storages = Storage.where(user_id: current_user)
end
def addQuantity
#storage = Storage.where(user_id: current_user.id)
#storage.update_all ("quantity = (quantity+200)")
redirect_to deliveries_url
end
def create
#delivery = Delivery.new(delivery_params)
respond_to do |format|
if #delivery.save
format.html do
render :nothing => true
end
format.json { render json: #delivery.to_json }
else
format.html { render :nothing => true} ## Specify the format in which you are rendering "new" page
format.json { render json: #delivery.errors } ## You might want to specify a json format as well
end
end
end
private
def delivery_params
params.require(:delivery).permit(:user_id, :ingredient, :quantity, :scenario_id)
end
end
New entries are created in the database, but whichever way I try to pass the user_id as param it isn't saved in the database.
I tried it like:
#delivery = Delivery.new(delivery_params, :user_id => current_user),
#user_id = current_user
#delivery = Delivery.new(delivery_params, #user_id)
and
params.require(:delivery).permit(:user_id, :ingredient, :quantity, :scenario_id).merge(user_id: current_user)
log:
Started POST "/deliveries" for 127.0.0.1 at 2014-11-03 12:59:37 +0100
Processing by DeliveriesController#create as */*
Parameters: {"delivery"=>{"ingredient"=>"meel", "quantity"=>"800", "scenario_id"=>"3"}}
Can't verify CSRF token authenticity
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'da39a3ee5e6b4b0d3255bfef95601890afd80709' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'da39a3ee5e6b4b0d3255bfef95601890afd80709' LIMIT 1
(0.0ms) begin transaction
SQL (0.2ms) INSERT INTO "deliveries" ("created_at", "ingredient", "quantity", "scenario_id", "updated_at") VALUES (?, ?, ?, ?, ?) [["created_at", "2014-11-03 11:59:37.253274"], ["ingredient", "meel"], ["quantity", 800], ["scenario_id", 3], ["updated_at", "2014-11-03 11:59:37.253274"]]
(12.5ms) commit transaction
Rendered text template (0.0ms)
Completed 200 OK in 24ms (Views: 0.8ms | ActiveRecord: 13.1ms)
but the user_id for Delivery stays nil. How would I pass the user_id from the current_user so it's saved in the database with the json I retrieve from the ajax call?
Thanks in advance
EDIT:
I fixed it the following way:
I send json data to javascript with content_tag:
= content_tag(:div,"", id: "storages", data:{url: Storage.where(user_id: current_user)})
this data is handled, and the user_id is suddenly accepted :)
thanks for the help!
Try this instead
#delivery = current_user.deliveries.new(delivery_params)
It should be
#delivery = Delivery.new(delivery_params.merge(user: current_user))
OR
#delivery = Delivery.new(delivery_params)
#delivery.user = current_user
Put current user_id on hidden field on HTML and send it with ajax like other params
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?
I am thankful to be in the presence of experts
I am trying to use range_field sliders to update some user params/integers.
When I submit the form, the params update temporarily in a <%= #user.risk %> text field I have off to the side, but do not save to the database, when I reload the changes are gone. I am drawing heavily from Michael Hartl's Rails 4.0 Tutorial.
Below I initially used form_for(#user) but current_user seems to work better overall.
`
<%= form_for(current_user) do |f|%>
<%= f.range_field :risk, :in=>0..100, :id=>"slider1"%>
<%= f.range_field :tax, :in=>0..100, :id=>"slider2"%>
<%= f.range_field :income, :in=>0..100, :id=>"slider3"%>
<%= f.range_field :international, :in=>0..100,:id=>"slider4"%>
<%= f.submit "Save Profile" %>
<% end %>`
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
sign_in #user
flash[:success] ="Welcome"
redirect_to #user
else
render 'new'
end
end
def edit
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:success] = "Profile Updated"
redirect_to #user
else render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation, :risk, :tax, :income, :international)
end
end
class User < ActiveRecord::Base
before_save :set_default
before_save { self.email = email.downcase }
before_create :create_remember_token
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with:
VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.encrypt(token)
Digest::SHA1.hexdigest(token.to_s)
end
def set_default
self.risk = "50"
self.tax = "50"
self.income = "50"
self.international = "50"
end
private
def create_remember_token
self.remember_token = User.encrypt(User.new_remember_token)
end
end
And the output at the console, after I try to update params via range_field, and input User.find(4)
=> #<User id: 4, name: "Tony", email: "2#g.c", created_at: "2013-09-23 06:37:22",
updated_at: "2013-09-23 06:37:23", password_digest: "...", remember_token: "...",
risk: 50, tax: 50, income: 50, international: 50>
This is the output of my local WEBRick Rails Server
Started PATCH "/users/1" for 127.0.0.1 at 2013-09-23 06:15:32 -0700
Processing by UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"...", "user"=>{"risk"=>"70", "tax"=>"61", "income"=>"54", "international"=>"58"}, "commit"=>"Save Profile", "id"=>"1"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", "1"]]
(0.0ms) begin transaction
User Exists (0.1ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('2#g.c') AND "users"."id" != 1) LIMIT 1
(0.0ms) rollback transaction
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '.....' LIMIT 1
(0.0ms) begin transaction
CACHE (0.0ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('2#g.c') AND "users"."id" != 1) LIMIT 1
(0.0ms) rollback transaction
Rendered users/edit.html.erb within layouts/application (1.9ms)
Rendered layouts/_header.html.erb (0.2ms)
Completed 200 OK in 8ms (Views: 6.0ms | ActiveRecord: 0.3ms)
Thank you all very much
The solution was simple
def update
#user = User.find(params[:id])
#user.update_attributes!(user_params)
.....