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: [],
)
Related
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.
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)
...
When creating a record in Rails Controller, the following error occurs :
Started POST "/spr_type_courses" for 127.0.0.1 at 2018-06-27 08:11:01
+0500 Processing by SprTypeCoursesController#create as HTML Parameters: {"spr_type_course"=>{}} Unpermitted parameter:
:spr_type_course Sequence (3.0ms) select us.sequence_name from
all_sequences us where us.sequence_owner = 'PROJECT' and
us.sequence_name = upper('SPR_TYPECOURSES_seq') Primary Key (10.0ms)
SELECT cc.column_name FROM all_constraints c, all_cons_columns cc
WHERE c.owner = 'PROJECT' AND c.table_name = 'SPR_TYPECOURSES' AND
c.constraint_type = 'P' AND cc.owner = c.owner AND cc.constraint_name
= c.constraint_name Primary Key Trigger (3.8ms) SELECT trigger_name
FROM all_triggers
WHERE owner = 'PROJECT'
AND trigger_name = q'[PROJECT.SPR_TYPECOURSES_PKT]'
AND table_owner = 'PROJECT'
AND table_name = q'[SPR_TYPECOURSES]'
AND status = 'ENABLED'
SQL (5.3ms) INSERT INTO "PROJECT"."SPR_TYPECOURSES"
("TYPECOURSE_ID") VALUES (:a1) [["typecourse_id", 3623]] Completed 500
Internal Server Error in 61ms
ActiveRecord::NotNullViolation (OCIError: ORA-01400: cannot insert
NULL into ("PROJECT"."SPR_TYPECOURSES"."DATE_BEGIN"): INSERT INTO
"PROJECT"."SPR_TYPECOURSES" ("TYPECOURSE_ID") VALUES (:a1)):
app/controllers/spr_type_courses_controller.rb:17:in `create'
What can this mean and what needs to be done to correct it?
class SprTypeCoursesController < ApplicationController
before_action :set_spr_type_course, only: [:show, :update, :destroy]
def index
#spr_type_courses = SprTypeCourse.all
render json: #spr_type_courses
end
def show
render json: #spr_type_course
end
def create
#spr_type_course = SprTypeCourse.new(spr_type_course_params)
if #spr_type_course.save
render json: #spr_type_course, status: :created, location: #spr_type_course
else
render json: #spr_type_course.erros, status: :unprocessable_entity
end
end
def update
if #spr_type_course.update(spr_type_course_params)
render json: #spr_type_course
else
render json: #spr_type_course.errors, status: :unprocessable_entity
end
end
def destroy
#spr_type_course.destroy
end
private
def set_spr_type_course
#spr_type_course = SprTypeCourse.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def spr_type_course_params
params.permit(
:typecourse_id,
:date_begin,
:date_end,
:name,
:comments,
:active_id
)
end
end
Your spr_type_course_params is the problem.
As you can see in the error log, the spr_type_course parameter is not being allowed in the strong parameters. Also, spr_type_course parameter is empty. Please review the submitted form too.
{"spr_type_course"=>{}} Unpermitted parameter:
Change it by the following:
def spr_type_course_params
# here I assume the typecourse_id, date_begin etc params are all
# included in spr_type_course schema
params.require(:spr_type_course).permit(
:typecourse_id,
:date_begin,
:date_end,
:name,
:comments,
:active_id
)
end
I migrated my Rails from 3.2 to Rails 4.2.6. I am having 2 tables where report :has_many => icons. I added strong parameters for report and icon_attributes. The create functionality is working fine and when coming to update functionality, I am able to update reports but couldn't update icons, instead new icon is created every time it hits update action.
This is my code:
report.rb:
class Report < ActiveRecord::Base
has_many :icons, -> { order 'position_id ASC'}
accepts_nested_attributes_for :icons, :reject_if => lambda { |a| a[:icon].blank? }, :allow_destroy => true
end
icon.rb:
class Icon < ActiveRecord::Base
belongs_to :report
end
reports_controller:
def update
respond_to do |format|
if #report.update_attributes(report_params)
#report.save
format.html { redirect_to(user_reports_url, :notice => 'Report was successfully updated.') }
format.json { render :json => { :success => true, :report_id => #report.id, :report_title => #report.title, :icon_array => #report.icons, :redirect => report_url(#report.id) } }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #report.errors, :status => :unprocessable_entity }
end
end
end
private
def report_params
params.require(:report).permit(:title, :comments, :remarks,{:icons_attributes => [:id, :icon, :rotation, :top, :_destroy]})
end
I have seen the log by putting puts in the controller, the icons are inserting at #report.update_attributes(report_params) step and this is the log:
Processing by ReportsController#update as JSON Parameters:
{"utf8"=>"✓", "report"=>{"title"=>"title1", "comments"=>"This is a comment",
"icons_attributes"=>{"0"=>{"id"=>"", "icon"=>"market_indicator",
"rotation"=>"0", "top"=>"", "_destroy"=>"false"}, "id"=>"87"}
Report Load (0.3ms) SELECT "reports".* FROM "reports" WHERE
"reports"."deleted_at" IS NULL AND "reports"."id" = ? LIMIT 1 [["id",
87]]
SQL (1.6ms) INSERT INTO "icons" ("icon", "rotation", "top")
VALUES (?, ?, ?) [["icon", "market"], ["rotation", "0"], ["top", ""],
["left", ""]] (12.0ms) commit transaction
ActiveRecord::Associations::CollectionProxy
I have put log as:
def update
puts #report.icons.inspect
respond_to do |format|
.....
end
it resulted as:
Icon Load (0.9ms) SELECT "icons".* FROM "icons" WHERE "icons"."report_id" = ? ORDER BY position_id ASC [["report_id", 91]]
<ActiveRecord::Associations::CollectionProxy [#<Icon id: 204, report_id: 91, icon: "asking_price", rotation: "", top: "150", left: "165">]>
Your "icon_attributes" is not passing the id of the icon along.
"icons_attributes"=>{"0"=>{"id"=>"", "icon"=>"market_indicator", "rotation"=>"0", "top"=>"", "_destroy"=>"false"}, "id"=>"87"}
You'll notice the id is blank. Since the id is blank rails thinks it is a new record and thus creates a new icon. The error lies in how you have made your form.
I have models
class Riskfactor < ActiveRecord::Base
has_many :bodies_riskfactors
has_many :bodies, through: :bodies_riskfactors
end
class Body < ActiveRecord::Base
has_many :bodies_riskfactors
has_many :riskfactors, through: :bodies_riskfactors
end
class DisordersArticle < ActiveRecord::Base
belongs_to :disorder
belongs_to :article
end
in view
= form_for [:admin, #riskfactor], html: {role: "form"} do |f|
= f.select :body_ids, Body.all.collect {|x| [x.name, x.id]}, {}, :multiple => true
and I have error on update
What could be wrong?
Processing by Admin::RiskfactorsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"CVkdBHLzLAeQ8FRFBVyonUuyn1FZAYG+X9fX/mmj+Bo=", "riskfactor"=>{"body_ids"=>["", "1"], "position"=>"1", "slug"=>"risk-factor-2", "name_ru"=>"High Blood Pressure", "published_ru"=>"no", "content_ru"=>"", "meta_description_ru"=>"", "meta_keywords_ru"=>"", "name_en"=>"High Blood Pressure", "published_en"=>"no", "content_en"=>"High Blood Pressure High Blood Pressure High Blood Pressure High Blood Pressure High Blood Pressure", "meta_description_en"=>"", "meta_keywords_en"=>""}, "button"=>"", "id"=>"4"}
User Load (0.3ms) SELECT users.* FROM users WHERE users.id = 1 ORDER BY users.id ASC LIMIT 1
Riskfactor Load (0.3ms) SELECT riskfactors.* FROM riskfactors WHERE riskfactors.id = 4 LIMIT 1
(0.1ms) BEGIN
Body Load (0.3ms) SELECT bodies.* FROM bodies WHERE bodies.id = 1 ORDER BY position LIMIT 1
Body Load (2.6ms) SELECT bodies.* FROM bodies INNER JOIN bodies_riskfactors ON bodies.id = bodies_riskfactors.body_id WHERE bodies_riskfactors.riskfactor_id = 4 ORDER BY position
Riskfactor::Translation Load (0.3ms) SELECT riskfactor_translations.* FROM riskfactor_translations WHERE riskfactor_translations.riskfactor_id = 4
Riskfactor Exists (0.6ms) SELECT 1 AS one FROM riskfactors WHERE (riskfactors.slug = 'risk-factor-2' AND riskfactors.id != 4) LIMIT 1
(0.2ms) ROLLBACK
Completed 500 Internal Server Error in 15ms
NoMethodError (undefined method body' for #<Riskfactor:0x007f9a0351c350>):
app/controllers/admin/riskfactors_controller.rb:45:inblock in update'
app/controllers/admin/riskfactors_controller.rb:44:in `update'
RiskfactorsController
class Admin::RiskfactorsController < Admin::BaseController
before_action :set_riskfactor, only: [:show, :edit, :update, :destroy]
def update
respond_to do |format|
if #riskfactor.update(riskfactor_params)
format.html { redirect_to [:edit, :admin, #riskfactor], notice: 'Riskfactor was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #riskfactor.errors, status: :unprocessable_entity }
end
end
end
private
def set_riskfactor
#riskfactor = Riskfactor.find(params[:id])
end
def riskfactor_params
params.require(:riskfactor).permit!
end
end
Imho the problem is that you have body_ids in your view, but you named you association as bodies. Try to rename body_ids to bodies_ids or something like that.