Rails 4 strong params formatting with multiple keys - ruby-on-rails

I working a service that takes in any number of custom attributes and serializes it into a hash.
So it would look something like this:
custom_contacts: {"address_book"=>
[{"contact_list"=>"user_data",
"contacts"=>[{"name"=>"user_data", "number"=>"user_data"},
{"name"=>"user_data", "number"=>"user_data"},
{"name"=>"user_data", "number"=>"user_data"}]}]}
The issue is that I can't quite seem to get this to play nicely with strong params in rails. I've read the documentation here and can't seem to wrap my head around how I would set this up.

You may need one "permit" like blow.
a = ActionController::Parameters.new(
{"data_key"=>
[{"name_key"=>"user_data",
"organization_key"=>[{"key1"=>"user_data", "key2"=>"user_data"},
{"key3"=>"user_data", "key4"=>"user_data"},
{"key5"=>"user_data", "key6"=>"user_data"}]}]}
)
a.permit(data_key: [:name_key, organization_key: [:key1, :key2, :key3, :key4, :key5, :key6]])

Related

Unpermitted parameters issue Ruby on Rails 5

I'm currently trying to understand how permitted parameters works in ruby.
Usually, in my_model.rb I have:
has_many: some_other_model
*
*
*
def my_model_params
params.require(:my_model).permit( :column1, some_other_model_attributes %i[other_column1])
etc...
and in the update function
my_object.update_attributes(my_model_params)
with a well formatted json which has some my_model root, and some_other_model_attributes as a child (array) with values.
My problem is I receive a json like this one
However the different arrays inside (such as codification, general_information) do contain attributes of the mission (general_information contains reference that is a column in the mission table) but there isn't any column named codification, or relation to a codification_attributes.
So, when I add :
general_information: %i[reference] in the permitted params, it says unknown attribute 'general_information' for Mission.
If not, no error are raised but in the log I can see unpermitted_parameter: general_information. And my object is not updated.
Finally if I reject it, there is no more unpermitted_parameter: general_information in the log but my object is not updated either.
I tried to set config.action_controller.action_on_unpermitted_parameters to false in my development config, it did nothing and it's probably a bad idea for production environment anyway.
The use of .permit! (even if it works) is currently not an option. And even though I think the json needs to be re-formatted it'd be better to find an other solution.
Thanks for the help.
unpermitted_parameter: ... in logs in not a problem which you need to fix, it's just an info.
How it works - you just permit needed parameters, you may think about them as a hash. Unpermitted parameters will not go into the model even if they are present in params. It means when you call
my_object.update_attributes(my_model_params)
it works like
my_object.update_attributes(column1: value_for_column1_from_params)
Keys in params should be named exactly as columns in the model, otherwise you need to prepare params somehow before create/update

Rails 4 Params Permit array of objects with arrays as values

I have a check_box_tag that returns me a permission object that I can't seem to permit.
I have checked on StackOverflow and tried a few things but since I am new to coding and params I can't get to make it work.
The params look like this:
"product_builder_permissions"=>[{"1"=>["1"], "2"=>["1"], "6"=>["42", "59"]}]
with the key of the nested hash being the id of the product builder and the values in the array the object id to which those builders have access to.
If I change a bit my HTML and get one key for each builder, I am able to whitelist with something such as params.permit(
product_builder_permissions1: [])
params.permit(
product_builder_permissions1: [])
etc.
which is inefficient.
I am trying to work with something like params.permit(product_builder_permissions:[0]) I only whitelist the key and value at the first level but not what's nested since I get
{"product_builder_permissions"=>[{}]}
I also tried something like
params.permit(product_builder_permissions:[0][:builder_id.to_s.to_i, :maker_id.to_s.to_i]) to no avail.
Thanks in advance.
Given that you're not doing mass assignment, I suggest you skip the heartache of strong parameters and just manipulate the parameters directly.

Rails: .require() without actually requiring it?

I'm trying to use...
params.require(:subscriber).permit(:utm_source, :utm_medium, :utm_campaign, :utm_term, :utm_content)
The problem is there are rare occasions where I want to do:
Subscriber.new(subscriber_params)
And I don't care if all the values are empty... When I do this it raises ActionController::ParameterMissing
So what I need is a way to make require() "optional" but still use it for the benefit of restricting nested parameters and for security, so people can't add in {admin: true} and things like that...
The actual params hash looks like:
{subscriber: {utm_source: 1, ...}
I can't change that part because it's used in many other places of the app. It's just this one spot.
You can use fetch instead of require:
params.fetch(:subscriber).permit(:utm_source, :utm_medium, :utm_campaign, :utm_term, :utm_content)
Check the rails guides for more information on strong parameters.

How to retrieve all attributes from params without using a nested hash?

I am currently in the process of making my first iphone app with a friend of mine. He is coding the front end while I am doing the back end in Rails. The thing is now that he is trying to send necessary attributes to me with a post request but without the use of a nested hash, which means that that all attributes will be directly put in params and not in a "subhash". So more specifically what I want to do is be able to retrieve all these attributes with perhaps some params method. I know that params by default contains other info which for me is not relevant such as params[:controller] etc.. I have named all attributes the same as the model attributes so I think it should be possible to pass them along easily, at least this was possible in php so I kind of hope that Rails has an easy way to do it as well.
So for example instead of using User.new(params[:user]) in the controller I have the user attributes not in the nested hash params[:user] but in params directly, so how can I get all of them at once? and put them inside User.new()?
I found the solution to my problem. I had missed to add the attr_accessible to my model which was what initially returned the error when I tried to run code like: User.new(params) having been passed multiple attributes with the post request.
The solution was very simple, maybe too simple, but since this is my first real application in Rails I feel that it might be helpful for other newbies with similar problems.
If you would like to just pass a more limited version of params to new, you should be able to do something like the following:
params = { item1: 'value1', item2: 'value2', item3: 'value3' }
params.delete(:item2)
params # will now be {:item1=>"value1", :item3=>"value3"}
Also see this for an explanation of using except that you mention in your comment. An example of except is something like:
params.except(:ssn, :controller, :action, :middle_name)
You can fetch the available attributes from a newly created object with attribute_names method. So in this special example:
u = User.create
u.attributes = params.reject { |key,value| !u.attribute_names.include?(key)
u.save

Iterating through array of Models in rails

Yet another ruby question but this is a bunch of questions in one. I'm really starting to like rails but there are some questions that I'd just like to ask straight out.
Right now, I'm implementing a queue in sqlite. I already have a scaffold setup with this working OK. The purpose is for a web crawler to read through the array and determine which links he should crawl next.
The architecture in the program is 2 controllers. one for Job and one for crawler. The Jobs has the standard Crud interface supplied by scaffold. Where I'm falling down is I'm still trying to understand how these things communicate with eachother.
The Job is formatted as a url:string and depth:decimal. The table is already populated with about 4 objects.
#sitesToCrawl = Job.all
#sitesToCrawl.each {|x|puts Job.url}
I have a bunch of questions about the above.
At the moment, this was supposed to display all the jobs and I foolishly thought it would display plain text but its actually a hexidecimal pointer to the object itself. What Im trying to do is iterate through the #sitesToCrawl and put out each Jobs url.
Questions start here:
1: I know ruby is dynamically typed. Will #sitesToCrawl become an array like i want it to be with each slot containing a job.
2: #sitesToCrawl.each is pretty straighforward and I'm assuming its an iterator.
is X the name od the method or what is the purpose of the symbol or string between |*|
3: Puts and print are more or less the same yes? if i say #x = puts 3 then would x be 3?
4: Job.url. Can objects be referenced this way or should I be using
##sitesToCrawl = db.execute("SELECT url FROM jobs;")
where db is a new database
As Rubish Gupta pointed out, in your block, you should do x.url, otherwise you're trying to access the url method on the class Job, not on instances of Job. In other words, in blocks, the items in the pipes are the arguments of the block, and each will iterate through your array, passing in one item at a time to your block. Check out the doc here.
Just to extend this idea, each on Hashes (associative arrays, maps, whatever you know them as) will pass two variables to your block: a key and a value, like this:
a_hash.each {|key_var, val_var| puts "#{key_var} is associated with #{val_var}"}
Also, it's been a bit since I've done plain ActiveRecord models, but you might look into doing
#sitesToCrawl = Job.all.to_a
since Job.all is a lazy finder in that it's building a query in potentia: you've essentially built a query string saying SELECT * FROM jobs, but it might not be executed until you try to access the items. each might do that, I can't remember off the top of my head, but if you're using a debugger to look at it, I know you need to_a to get it to run the query.
You should absolutely be using job_instance.url - that's the beauty of ActiveRecord, it makes database access easy, provided everything gets set up right :)
Finally, puts and print are almost the same - the difference is that puts "string" is essentialy print "sting"; STDOUT.flush - it flushes at the end of the statement.

Resources