Assign/Replace Params Hash in Rails

assign/replace params hash in rails

The params which contains the request parameters is actually a method call which returns a hash containing the parameters. Your params = line is assigning to a local variable called params.

After the if false block, Ruby has seen the local params variable so when you refer to params later in the method the local variable has precedence over calling the method of the same name. However because your params = assignment is within an if false block the local variable is never assigned a value so the local variable is nil.

If you attempt to refer to a local variable before assigning to it you will get a NameError:

irb(main):001:0> baz
NameError: undefined local variable or method `baz' for main:Object
from (irb):1

However if there is an assignment to the variable which isn't in the code execution path then Ruby has created the local variable but its value is nil.

irb(main):007:0> baz = "Example" if false
=> nil
irb(main):008:0> baz
=> nil

See: Assignment - Local Variables and Methods in the Ruby docs.

Rails 6 change params to hash of hashes

The params get his structure from the input names.

So you could add an hidden field for question, and then specify a name for both of your fields.

<%= simple_form_for :test_results, url: test_results_path  do |f| %>
<% @randomize_questions.map do |q| %>
<%= q[:question] %>
<%= f.input "question_#{q[:id]}", as: :hidden, input_html: { name: "test_results[#{q[:id]}][question]", value: q[:question] } %>
<%= f.input "question_#{q[:id]}", collection: q[:answers], as: :radio_buttons, input_html: { name: "test_results[#{q[:id]}][answer]" } %>
<% end %>
<%= f.button :submit %>
<% end %>

Params should looks like this:

params => {
test_result: {
1 => {
question: "...",
answer: "..."
},
2 => {
question: "...",
answer: "..."
}
}
}

Not tested. Could you tell if that's works for you?

Modify ruby hash in place( rails strong params)

permit returns a new hash with those keys in it, so you're not modifying the real params variable. You're also not saving a reference to the hash trip_params returns, so you get it fresh each call in save.

Try this:

def save
tp = trip_params
tp[:name] = 'Modifying name in place'
# ... use tp later, it'll be in there
end

Or, if you really want it to be used the way you previously did, modify trip_params like so:

def trip_params
@trip_params ||= params.require(:trip).permit(:name, :date)
end

Now that hash is lazily cached and the same one is returned on subsequent trip_params calls.

Modifying the params hash in Rails

The params hash is special since (especially with forms) is it mapped one-for-one with the model(s) it is related to, and Rails expects there to be either a database column, or a method in the model having that name.

Hidden fields are the typical solution to the problem of getting at additional data, but if you don't want users to see those fields, you run into the problem that HTTP is stateless. So in this case, the session[:something] is your friend. Before displaying a form or page that may have hidden data, instead add the data to a session variable (encrypt it first), which you can then read (and decrypt) when the user submits the form. Or you can save it in a database table and put only the row id in the session so the data can be read back when the form is posted.

If the data was part of the model, but you just didn't want to display it, you could just display the parts the user could see in the view, but then look up the rest of it in the controller action when the user submitted the form or request.

If the data is not sensitive you can just make sure to declare the values that the user can change as attr_accessible in their respective models (prevents mass assignment) and put the others in hidden fields.

Editing params nested hash


still keep the output as a params hash (still containing nested hashes arrays

Sure.

You'll have to manipulate the params hash, which is done in the controller.

Whilst I don't have lots of experience with this I just spent a bunch of time testing -- you can use a blend of the ActionController::Parameters class and then using gsub! -- like this:

#app/controllers/your_controller.rb
class YourController < ApplicationController
before_action :set_params, only: :create

def create
# Params are passed from the browser request
@model = Model.new params_hash
end

private

def params_hash
params.require(:x).permit(:y).each do |k,v|
v.gsub!(/[regex]/, 'string')
end
end
end

I tested this on one of our test apps, and it worked perfectly:

Sample Image

Sample Image

Sample Image

--

There are several important points.

Firstly, when you call a strong_params hash, params.permit creates a new hash out of the passed params. This means you can't just modify the passed params with params[:description] = etc. You have to do it to the permitted params.

Secondly, I could only get the .each block working with a bang-operator (gsub!), as this changes the value directly. I'd have to spend more time to work out how to do more elaborate changes.

--

Update

If you wanted to include nested hashes, you'd have to call another loop:

def params_hash
params.require(:x).permit(:y).each do |k,v|
if /_attributes/ ~= k
k.each do |deep_k, deep_v|
deep_v.gsub!(/[regex]/, 'string'
end
else
v.gsub!(/[regex]/, 'string')
end
end
end

How to change value in params array in Ruby on Rails?

If vendor_params is a strong_params method (which I'm assuming it is), it actually creates a new hash. So when you alter vendor_params... you're not actually changing your original params hash.

OK, why isn't vendor_params changing though... I dont care about params? WELL, vendor_params still points the original params hash assuming it looks something like:

def vendor_params
params.require(:vendor).permit(:price)
end

I think the link below is a similar issue and may present a useful solution. Hope I understood your problem correctly!

Modify ruby hash in place( rails strong params)

How to replace a hash key with another key


hash[:new_key] = hash.delete :old_key

How to change Hash values?


my_hash.each { |k, v| my_hash[k] = v.upcase } 

or, if you'd prefer to do it non-destructively, and return a new hash instead of modifying my_hash:

a_new_hash = my_hash.inject({}) { |h, (k, v)| h[k] = v.upcase; h } 

This last version has the added benefit that you could transform the keys too.

Rails Controller action: Customize key in params hash

This is currently very wrong.

In order to make this work as it should, you should create a route like this

resources :widgets do
get 'comments' => 'comments#index'
post 'comments' => 'comments#create'
end

and when posting to this CommentsController, you pass in the comment info correctly in the prams[:comment].

Your controller would have actions like this

def create
widget = Widget.find(params.delete :widget_id)
comment = widget.comments.create(params[:comment])
end


Related Topics



Leave a reply



Submit