I've been tinkering with the Rails 5.0 permit function for quite some time now, but I just can't get it right and really need some help:
I have this white listing function. And when executed I get the following response:
Unpermitted parameter: studio_users_attributes
I have this white listing function
def studio_params
params.require(:studio).permit(:name, :name_long, :address, :address2,
:zip, :city, :country, :phone,
:entity_id, { studio_users_attributes: [] } )
end
The params method returns me following:
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"VZTPSpsmNJxcqc[...]",
"studio"=>{"studio_users_attributes"=>{"0"=>{"viewing_rights"=>"Nur eigene",
"id"=>"4"}, "1"=>{"viewing_rights"=>"Alle", "id"=>"5"}}},
"commit"=>"Studio aktualisieren", "controller"=>"studios",
"action"=>"update", "id"=>"2"
}
Some help would be highly appreciated.
Philipp
In the controller you use studio_users_params.
But you send studio_users_attributes.
After some more experimenting I managed to solve it.
For the nested parameters I had to explicitly add the keys to the nested-hash:
def studio_params
params.require(:studio).permit(:name, :name_long, :address, :address2, :zip,
:city, :country, :phone, :entity_id,
studio_users_attributes: [:id, :viewing_rights] )
Leaving the hash empty (studio_users_attributes: []), would still result in
"Unpermitted parameter: studio_users_attributes "
Related
params.permit(
:type,
payload: [
user: [
:id, :email, :isAnonymous, :isAdmin, :firstName, :createdAt, :updatedAt, :phone, :inviteCode, :employeeId, :activated, :lastName,
:locked, :authVersion, :isCompanyAdmin, :isEditor, :isAnalyst, :isManager, :seenWebOnboarding, :language, :hidden, :deleted, :isSuperAdmin, :hasSignedInAsLearner,
:hasCreatedCourse, :hasInvitedAdmins, :isCompanyOwner, :sendActivationReminders, :timezone, :isUnsubscribedFromEngagementEmails, :authType, :activatedDate, :shouldShowGamificationOnboarding, :depositedPoints, :name,
:identifiers
],
course: [
:id, :customerId, :title, :courseKey, :public, :icon, :createdAt, :updatedAt, :courseImageUrl, :colour, :published, :type,
:requiresEnrolment, :isSample, :completionMessage, :completionButtonUrl, :completionButtonText, :isHidden, :learnersCount
],
parentGroup: [
:id, :customerId, :name, :createdAt, :updatedAt, :parentGroupId, :welcomePageConfigId, :selfSignupConfigId, :language, :deleted,
:ssoConfigId, :cookieConsentDisabled, :usersCount, :activatedUsersCount
],
completion: [
:overallAssessmentScore, :overallLessonScore, :scoresBreakdown, :courseStartDate, :courseCompletionDate,
:courseCompletionDurationInSeconds, :completionLanguage
]
],
:timestamp).to_h
end
This is the code that I'm having an issue with. When I try making a call to this endpoint, I run into this error.
syntax error, unexpected ')', expecting =>
:timestamp).to_h
^ excluded from capture: Not configured to send/capture in environment 'development'
I've noticed if I put the timestamp before the payload in the params.permit than this issue isn't there anymore. However, this is not how the request is going to formatted and I need to follow the structure of the request as it determines a hash later on in the code. Anyone know how to resolve this?
Even though you can do this in a method call, you can't have hash-style elements in a Ruby array. You need to have a formal hash inside of the array itself.
You need to split it out explicitly:
params.permit(
:type,
{
payload: [ ... ]
}
)
From further research, it seems that having a nested attributes must be permitted last. Makes sense as to why this only occurs when timestamp is behind payload.
I'm going to deal with this by just creating a new hash with the params later on with the correct structure.
source: https://smartlogic.io/blog/permitting-nested-arrays-using-strong-params-in-rails/
I am maintaining a current Web Application (Ruby on Rails).
Our client wanted me to add this attributes contacts_attributes: [:id, :stock_holding_status] to the method below:
def meeting_log_params
params.require(:meeting_log).permit(
:id,
:stock_id,
:ir_meeting_id,
:start_at,
:end_at,
:kind,
:meeting_type,
:request_agent_company,
:request_agent_name,
:minute_taker,
:subject,
:content,
:memo,
:rating,
:country,
:city,
:attachment_1,
:remove_attachment_1,
:attachment_2,
:remove_attachment_2,
:attachment_3,
:remove_attachment_3,
interviewers_attributes: [
:id,
:meeting_log_id,
:resource_id,
:resource_type,
:_destroy
],
speakers_attributes: [
:id,
:meeting_log_id,
:resource_id,
:resource_type,
:_destroy
],
meeting_log_contacts_attributes: [
:stock_id,
:company_name,
:name,
],
ir_guests_attributes: [
:stock_id,
:department,
:title,
:last_name,
:first_name,
:department_en,
:title_en,
:last_name_en,
:first_name_en,
]
)
end
It is just that it returns me a 422 error (which means unprocessable entity) every time I used the added attribute on this method below.
Contact.update_stock_holding_statuses(meeting_log_params[:contacts_attributes])
I think it is because of the required(:meeting_log) that was before the permit method. Can you tell me how to exempt the required(:meeting_log) if I am going to use the added attribute on certain methods?
Like what I have in mind is like this:
params.require(:meeting_log ? :meeting_log : nil).permit( <all_attributes>)
I tried using ternary operators to exempt/disable the required part for me to use the added attribute which is contacts_attributes: [:id, :stock_holding_status] on a specific method and prevent the 422 from interfering. But it didn't work.
Any suggestions please.
Thank you!
How about simply
permitted_attributes = [:id,
:stock_id,
:ir_meeting_id,
:start_at,
:end_at,
:kind,
...
]
def meeting_log_params
meeting_log ? params.require(:meeting_log).permit(permitted_params) : params.permit(:permitted_params)
As far as I know, if the input parameters do not match require.permit, then you will get code 400 (not 422).
Code 422 is most likely related to the validation of the model when inside the update_stock_holding_statuses method.
While creating new Student Im getting error "no implicit conversion of Symbol into Integer"
In Students Controller,
def student_params
params.require(:student).permit(:name, :lastname, :subjects_attributes [:id, :name :_destroy, :mark_attributes [ :id, :value ]] )
end
What causes this problem ?
The problem is here:
:subjects_attributes [:id, :name :_destroy, :mark_attributes [ :id, :value ]] )
You should have a colon(:) after subject_attributes, not before it.
You can do either :subject_attributes => [:id, :name, :_destroy...] or subject_attributes: [:id, :name, :_destroy...]
The syntax without => is used with Ruby 2.0+, and is preferred one.
Bilal is correct. Also, you'll have to change :mark_attributes to mark_attributes:.
Why?
:subjects_attributes is a symbol. But subjects_attributes: [ ] is a hash where the key is :subjects_attributes (a symbol, as it turns out) and the value is [ ].
So, strong parameters knows how to process the hash defined by subjects_attributes: [ ] just fine.
But a symbol followed by an array, like :subjects_attributes [ ]? Well, that makes for all kinds of unhappiness accompanied by falling on the floor, kicking, and screaming.
As Bilal also points out, you can get back to a place of happiness by doing :subjects_attributes => [ ], which also creates hash and makes the sun shine again.
And that, my friend, is the answer to the question "What causes this problem?"
I am getting params as follows.
{"utf8"=>"✓", "authenticity_token"=>"auth_token=", "js_data_entry"=>[{"data_entry"=>[{"name"=>"test_book22", "node_id"=>"65", "field_type"=>"Text", "options_attributes"=>[{"option_value"=>""}], "location"=>"Body", "rank"=>"", "must_fill"=>"0", "multi"=>"0", "role"=>["4"], "update_db"=>"vocation.name", "select_db"=>""}], "js_editor"=>[{"field_id"=>"", "field_class"=>"", "js_code"=>""}]}], "node_id"=>"65", "commit"=>"Submit", "action"=>"create", "controller"=>"data_entries"}
I tried to permit params as follows
def entry_params
params.require(:js_data_entry).permit([:node_id, :field_type, :name, :location, :rank, :multi, :must_fill, :update_db, :select_db, :role, :options_attributes])
end
but it's throwing
undefined method `permit' for #<Array:0xc603e78>
Please help me to fix this issue.
I fixed the issue as follows..
params.require(:js_data_entry)[0].permit(:data_entry=>[:node_id, :field_type, :name, :location, :rank, :multi, :must_fill, :update_db, :select_db, :role=>[], :options_attributes=>[:option_value]], :js_editor=>[:field_id,:field_class,:js_code])
I'm posting the following JSON to the rails create method in my 'user_controller' controller class.
{"user_detail_attributes":
{
"login":"dan123456",
"password":"password",
"password_confirmation":"password"
},
"surname":"REST_TEST",
"firstname":"REST_TEST",
"phone":"0456782",
"grad_year":2010,
"jobs":false,
"email":"REST_TEST#EMAIL.co.uk"
}
My user_params are as follows:
params.require(:user).permit(
:surname, :firstname, :phone, :grad_year, :jobs, :email,
user_detail_attributes: [:id, :password, :password_confirmation, :login])
Rails should then map this json to the user.
So the params variable should contain a user, inside that user should be the attributes including the user_detail_attributes.
However the user_detail attributes are appearing outside the user params variable as a completely seperate params variable, on the same level as the users params.
So, what should be happening:
user
+surname
+firstname
.
.
.
+user_detail_attributes
+login
+password
+password_confirmation
What's actually happening:
user_detail_attributes
+login
+password
+password_confirmation
user
+surname
+firstname
.
.
.
This then leads to the user being mapped to the user table in my database but no user_details being mapped to that table.
Does anyone know why this is happening and whether I can fix it? And if it is something that I need to do with the JSON format or something in the rails application.
Thanks,
Dan
EDIT: Fixed
According to the Strong Parameters Documentation
You should be doing something like this:
parameters.require(:user).permit(:surname, :firstname, :phone, :grad_year, :jobs, :email, {user_detail_attributes: [:login, :password, :password_confirmation] })
Note the {} before and after the user_detail_attributes
My test in console
hash = {user: {user_detail_attributes: { login: "dan123456", password: "password", password_confirmation: "password"}, surname:"REST_TEST", firstname:"REST_TEST", phone:"0456782", grad_year:2010, jobs:false, email:"REST_TEST#EMAIL.co.uk"} }
params = ActionController::Parameters.new(params)
parameters.require(:user).permit(:surname, :firstname, :phone, :grad_year, :jobs, :email, {user_detail_attributes: [:login, :password, :password_confirmation] })
Outuput:
{"surname"=>"REST_TEST", "firstname"=>"REST_TEST", "phone"=>"0456782", "grad_year"=>2010, "jobs"=>false, "email"=>"REST_TEST#EMAIL.co.uk", "user_detail_attributes"=>{"login"=>"dan123456", "password"=>"password", "password_confirmation"=>"password"}}
I've worked out the problem.
The JSON should be formatted as follows:
{"user":
{"user_detail_attributes":
{
"login":"dan123456",
"password":"password",
"password_confirmation":"password"
},
"surname":"REST_TEST",
"firstname":"REST_TEST",
"phone":"0456782",
"grad_year":2010,
"jobs":false,
"email":"REST_TEST#EMAIL.co.uk"
}
}
I was missing the user attribute at the start as this was how my c# JSON encoder was formatting the JSON from my user and user_detail_attribute classes.
I had a play around by creating the JSON manually and this turned out to be the fix.
Thanks for everyone's help :)