How to update values that depend on strong params - ruby-on-rails

I have an action (using strong parameters) in controller:
def home_task_params
params.require(:home_task).permit(:subject, :description, :data)
end
I want to modify the data before recording to the database. I want to do something similar to this:
def create
#home_task = HomeTask.create(
:subject => home_task_params.subject,
:description => home_task_params.description,
:day => home_task_params.data,
:data => home_task_params.data,
:class_room => current_user.class_room
)
end
How do I implement it?

params is an object that behaves like a hash. Therefore you cannot read values from that object like this params.subject instead, you have to use params[:subject].
Something like this might work:
#home_task = HomeTask.create(
:subject => home_task_params[:subject],
:description => home_task_params[:description],
:day => home_task_params[:data],
:data => home_task_params[:data],
:class_room => current_user.class_room
)
Or you could just merge the additional values to params:
#home_task = HomeTask.create(
home_task_params.merge(
day: home_task_params[:data],
class_room: current_user.class_room
)
)

Related

Access params with wildcard in Rails

At the moment I have a form_tag which contains inputs and puts these inputs into parameters.
I want to be able to loop over them in the controller action.
I've tried getting all params excluding all the usual params (action, controller, model name etc.) and then using a wildcard like params[:prop*].
Here is the offending form inputs:
%input{:name => "userEmails", :id =>"userEmails", :type => "hidden", :value => ""}
-#all_properties.each do |prop|
%input{:name => "prop"+prop.name+"checkbox", :type => "checkbox", :id => "prop"+prop.name+"checkbox"}
#{prop.name}
%input{:name => "prop"+prop.name, :type => "text", :id => "prop"+prop.name}
These show up in params like {"propProperty1checkbox"=>"on", "propProperty1" => "testing", "propAnotherPropertycheckbox" => "on", "propAnotherProperty" => "another test value"} etc.
I'm unsure how to access these as the names of the properties can change and so need to be accessed abstractly.
You can use #select on params hash to filter only the params that are interesting for you:
params = {"user_id"=>1,
"propProperty1checkbox"=>"on",
"propProperty1"=>"testing",
"propAnotherPropertycheckbox"=>"on",
"propAnotherProperty"=>"another test value"
}
params.to_h.select{|key, value| key =~ /^prop/}
#=> {"propProperty1checkbox"=>"on",
#"propProperty1"=>"testing",
#"propAnotherPropertycheckbox"=>"on",
#"propAnotherProperty"=>"another test value"}
EDIT
Example from the comment:
[13] pry(main)> {"utf8"=>"✓", "_method"=>"put", "authenticity_token"=>"xxxxx", "userEmails"=>"teste#test.com,test2#test.com,test4#test.com,fasd#gmail.com", "propProperty1checkbox"=>"on", "propProperty1"=>"3", "propAnotherPropertycheckbox"=>"on", "propAnotherProperty"=>"4", "commit"=>"Submit", "Application"=>"8", "Company"=>"1" }.to_h.select{|k, v| k =~ /^prop/}
=> {"propProperty1checkbox"=>"on",
"propProperty1"=>"3",
"propAnotherPropertycheckbox"=>"on",
"propAnotherProperty"=>"4"}
You can try something like:
input(name: "props[#{pro_name}][checkbox]"...)
input(name: "props[#{pro_name}][text]"...)
Then, in your controller:
def method
props = params[:props]
props.each do |property_name, values|
chk = values[:checkbox]
text = values[:text]
end
end

Searching with multiple conditions (Ruby on Rails)

I want to search a table with multiple conditions in Rails.
I am working on deleting certain package(record) from database but first i need to get userId and packageID .
and here is the code i wrote but it gives error.
#package=Packages.find(:all, :condition => {:id => params[:pid]}, :condition => {:senders_id => cookies[ :user_id ]})
here is the error :
ArgumentError in CreatePackagesController#deletepackage
Unknown key: condition
i just need equivalent code with the right syntax to that one if someone could help.
def deletepackage
#package=Packages.find(:all, :conditions => {:id => params[:pid], :senders_id => cookies[ :user_id ]}
if (#package!=nil && req.receivedByCarrier==false)
#package.destroy
elsif (#package!=nil && req.receivedByCarrier==true)
#package.destroy
end
return;
end
Change your query as below:
#package = Packages.find(:all, :conditions => {:id => params[:pid], :senders_id => cookies[:user_id]})
You are getting the error as Unknown key: condition because :condition is not a valid option in find method.
:condition should be :conditions (Note plural). Also, you should be passing both the conditions as a single key-value pair.
For Rails 4.x
You can simply do it as below
#package = Packages.where(id: params[:pid], senders_id: cookies[:user_id])
This
#package=Packages.find(:all, :condition => {:id => params[:pid]}, :condition => {:senders_id => cookies[ :user_id ]})
should be like this
#package=Packages.find(:all, :conditions => {:id => params[:pid]}, :senders_id => cookies[ :user_id ]})

Ruby on Rails Model creation string not converted to integer

Here is my code:
base_release_id column in release db is integer type
form.html.haml
= form_for #release do |f|
= f.label :name
%br
= f.text_field :name
....
= f.label :base_release_id
%br
= f.select :base_release_id, options_from_collection_for_select(conditionsPlusBlankOrderBy(Release),"id","name",#release.base_release_id)
= f.submit
releases_controller.rb
def create
ap params
#release = Release.new(params[:release])
ap #release
...
end
I was going to create a new release including its name , base release id etc.
I was using 2 "ap" to trace the release object. strange thing happen. See my log below:
{
"utf8" => "â",
"authenticity_token" => "8HdDlC3jJxYvq+8tUh/cut5ibHxjIF6L2CzAFORlNBg=",
"release" => {
"name" => "e",
"code" => "e",
"base_release_id" => "2"
},
"commit" => "Create Release",
"action" => "create",
"controller" => "releases"
}
#<Release:0x000000190f06b8> {
:id => nil,
:name => "e",
:code => "e",
:base_release_id => nil,
}
Processing by ReleasesController#create as HTML
Parameters: {"utf8"=>"â", "authenticity_token"=>"8HdDlC3jJxYvq+8tUh/cut5ibHxjIF6L2CzAFORlNBg=", "release"=>{"name"=>"e", "code"=>"e", "base_release_id"=>"2"}, "commit"=>"Create Release"}
Not sure why base_release_id lost, name and code is working.
I have the similar code works in other page, in which case parame string value don't parsed to model integer?
it works if i added the datatype convertion as below:
def create
ap params
#release = Release.new(params[:release])
#release.base_release_id = params[:release][:base_release_id].to_i if params[:release][:base_release_id]
ap #release
...
end
Please help and thank you in advance.
found why.
in my model release.rb, i'v defined "attr_accessible :id, :name, :code, :as => :tmp_use". Then it accept id, name and code only. After i added :base_release_id, it works.
not sure how :as => :tmp_use work. I suppose default all variable can be accessed. In some places, i was using
Release.new("id"=>row[:id],"name"=>row[:name],"code"=>row[:code], :as => :tmp_use)
Some places i don't want to do it i want to all columns be accessable.
No sure how.
Thank you Ivan anyway.

How to update attributes only if the params are defined?

currently in my update controller method I have:
#group.attributes = {
:title => params[:group][:title],
:description => params[:group][:description],
:password_required => params[:group][:password_required],
:password => params[:group][:password],
:archived => params[:group][:archived]
}
The problem is that this method is used in multiple places and all of these params are not always passed which results in a "nil" which causes the db commit to rollback.
How can you set attributes only when they are defined w/o having to use if blocks?
Thanks
Could probably do something lousy like this:
#group.attributes = {
:title => params[:group][:title] || #group.title,
:description => params[:group][:description] || #group.description,
:password_required => params[:group][:password_required] || #group.password_required,
:password => params[:group][:password] || #group.password,
:archived => params[:group][:archived] || #group.archived
}
This kind of ugly code is not recommended, but it answers the question of how to do this without explicit if blocks.
why not simplify it with
#group.update_attributes(params[:group])
this way if the value us nil it wont be updated

Passing different parameter to a method call depending on a condition in Ruby

This is the code for my function, in which I am making a call to new
def create_person_detail_from_registration(type, registration, registration_detail)
person_detail = type.constantize.new(
:email => registration.email_2,
:phone_1 => registration_detail.phone_1,
:phone_2 => registration_detail.phone_2,
:phone_3 => registration_detail.phone_3,
:phone_4 => registration_detail.phone_4,
:phone_5 => registration_detail.phone_5,
:phone_6 => registration_detail.phone_6,
:phone_7 => registration_detail.phone_7,
:address_1 => registration_detail.address_1,
:address_2 => registration_detail.address_2,
:city => registration_detail.city,
:state => registration_detail.state,
:postal_code => registration_detail.postal_code,
:country => registration_detail.country
)
return person_detail
end
Now the issue is depending on what value type has, :email is either set to registration.email_2 or registration.email. One way of doing that is of course, to write the whole code twice surrounded by an if-elsif statement. But I just wanna know, if there's any smarter, more elegant way of doing this?
Just add the condition into value .
:email => (type==1 ? registration.email_2 : registration.email),

Resources