No implicit conversion of Symbol into Integer, nested forms - ruby-on-rails

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?"

Related

Resolving ruby params.permit syntax error

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/

Exempt an attribute in require method

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.

Confusion between hashes and symbols

May you help me understand the concept behind the hash and especially when we use symbols.
:name is a symbol right ?
we can use symbol as a key for our hashed right ?
:name and name: for example : those are two syntaxes but it describes a symbol right ?
when we have this for example :
Geocode.configure(
units: :km
)
here units does a reference to a specified argument called units in the configure function right ? and :km is the symbol we want to send through the variable unit or am I wrong ?
A last example :
validates :home_type, presence: true
Here we try to send to the validates function the symbol home_type right ?
and the second argument is named "presence" and we want to send the boolean true through this variable right ?
I am sorry if you don't understand my question, don't hesitate to ask me.
I got many headeck nderstanding those syntaxes.
Thanks a lot !
Geocode.configure(units: :km)
We are passing an hash to the configure method. This hash {units: :km}. Convenient syntax for {:units => :km}. So an hash with a key value pair with key symbol (:units) and value symbol (:km).
validates :home_type, presence: true
Here we are passing to the validates method a symbol :home_type and an hash, {presence: true}, or {:presence => true}. So the key is :presence symbol, the value is the boolean true.
It is very basic & nothing but simplified convention in ruby
validates :home_type, presence: true, if: :check_user
is similar to
validates :home_type, { :presence => true, :if => :check_user }
So when I write as,
link_to 'Edit', edit_path(user), class: 'user_one', id: "user_#{user.id}"
In above, link_to is ActionHelper method which is taking 3 arguments where last one is hash { class: 'user_one', id: "user_#{user.id}" }

Make new hash from {"sample" => "sample"} to {:sample => "sample"}

In condition,
COLUMN = [:id, :tag_list, :price, :url, :Perweight, :Totalweight, :memo, :created_at, :updated_at]
row = {"id"=>4, "tag_list"=>"peanuts", "price"=>100, "Totalweight"=>390, "Perweight"=>nil, "url"=>nil, "memo"=>nil, nil=>nil}
from these two conditions, I want to make above Hash Object.
{:id=>4, :tag_list=>"peanuts", :price=>100, :Totalweight"=>390, :Perweight=>nil, :url=>nil, memo=>nil}
I tried, like this...
at first, I make empty hash,
new = Hash[COLUMN.zip([])]
p new
--->
{:id=>nil, :tag_list=>nil, :price=>nil, :url=>nil, :Perweight=>nil, :Totalweight=>nil, :memo=>nil, :created_at=>nil, :updated_at=>nil}
and then, I dont know how to do that,
Please give me advice?
You can use Symbolize Keys.
row.symbolize_keys
or destructively
row.symbolize_keys!

Permitting array of arrays with strong parameters in rails

I have searched everywhere but does anyone know if it is possible to permit and array of arrays using strong parameters in rails? My code looks like this:
params.require(:resource).permit(:foo, :bar => [[:baz, :bend]])
This is giving me:
ArgumentError (wrong number of arguments (0 for 1..2))
I have also tried:
params.require(:resource).permit(:foo, :bar => [[]])
params.require(:resource).permit(:foo, :bar => [][])
params.require(:resource).permit(:foo, :bar => [])
But these all give me invalid parameter errors or do not process the parameters.
Thanks in advance for any help
Looking at the code I think this is not possible. you have to flatten the second level.
def permit(*filters)
params = self.class.new
filters.each do |filter|
case filter
when Symbol, String
permitted_scalar_filter(params, filter)
when Hash then
hash_filter(params, filter)
end
end
unpermitted_parameters!(params) if self.class.action_on_unpermitted_parameters
params.permit!
end
Here's an example taken from rails strong parameter Github page:
params.permit(:name, {:emails => []}, :friends => [ :name, { :family => [ :name ], :hobbies => [] }])

Resources