I have some checkboxes on one view, that I want to eval on another, but I dont understand what its doing.
I've read posts/blogs stating different approaches to the name :-
update_params[] # array
update_params[0], update_params[1] # known indexed array
update_params0, update_params1 # differently named
So going with the first which seems the most common :-
# views/index.erb
<input type="checkbox" name="update_params[]" value="Copy" />Update the host<br/>
<input type="checkbox" name="update_params[]" value="Start" />Start the software<br/>
Should the value be indexed? 0, 1?
So I want two outcomes
1) Display the options selected from the index.erb view on the version.erb view.
So that it looks something like :-
Copy : Yes
Start : No
Currently I have :-
# views/version.erb
<p>Copy : <%= params['update_params[0]'] %></p>
<p>Start : <%= params['update_params[1]'] %></p>
2) eval the options to pass to a script so that they become command line options, ie -c, -l
So my "controller"
# update.rb
helpers do
def run_update(version, host, params)
command = "./update.sh #{params} #{host}" # -c -l
#ok = system( command )
end
end
post '/version' do
run_update(params[:version_list], params[:host], params[:update_params])
erb :version
end
Maybe instead of relying on index, you could use keys in the array? For example:
<input type="checkbox" name="update_params[copy]" value="Copy" />Update the host<br/>
<input type="checkbox" name="update_params[start]" value="Start" />Start the software<br/>
So then, you can do stuff like:
params[:update_params][:copy]
Related
I have a custom Rails form that would look like the following :
<form action="/download/zip" id="multifile" method=POST>
<!-- Here is a react component that makes a loop of every record I have of uploaded files, with a checkbox before each of them, that would look like the following -->
<label><input type="checkbox" value={ this.props.file.path } /> { this.props.file.filename } </label>
<input type="submit" value="Download" />
</form>
I choose not to use form_for since the values I want to submit aren't linked to a Model (But if needed, I can use it).
The external controller is here to create a zip of every file selected. It works if I modify the method to 'get' and if I ask to download everything.
So far, here is how it looks:
class DownloadController < ApplicationController
require 'zip'
def zip
abort #params.inspect # returns 'nil'
zip_tmp = File.new("#{Rails.root}/public/zip-#{Time.now.strftime('%d%m%Y')}.zip", 'w+')
Zip::File.open(zip_tmp.path, Zip::File::CREATE) do |zipfile|
FileDetail.all.each do |file| # This works with route set to get
zipfile.add(file.path.split('/')[-1], '/home/username/DEV/rails-react-project/public' + file.path)
end
end
send_file "#{Rails.root}/public/zip-#{Time.now.strftime('%d%m%Y')}.zip"
end
private
def params
#params
end
end
I correctly get redirected to the controller, however when I check if there are some datas to work on, I get nil back.
What would be the "correct" way to do so?
Thank you in advance
(P.S. I know I'll have some issues with this actual code if it works, but gettings datas through the parameter would be nice to start with)
I see it is already commented the mistake but I would like to edit your code and post as answer as it will helpful to other.
Form :
<form action="/download/zip" id="multifile" method=POST>
<!-- Here is a react component that makes a loop of every record I have of uploaded files, with a checkbox before each of them, that would look like the following -->
<label>
<input type="checkbox" name="my_param_name[]" value={ this.props.file.path } /> { this.props.file.filename }
</label>
<input type="submit" value="Download" />
</form>
Controller :
class DownloadController < ApplicationController
require 'zip'
def zip
# This will return array of files user has selected in form
# You can use this to process further to generate zip
files_list = params[:my_param_name]
suffix = Time.now.strftime('%d%m%Y')
zip_file_name = "#{Rails.root}/public/zip-#{suffix}.zip"
zip_tmp = File.new(zip_file_name, 'w+')
Zip::File.open(zip_tmp.path, Zip::File::CREATE) do |zipfile|
FileDetail.all.each do |file| # This works with route set to get
zipfile.add(file.path.split('/')[-1], '/home/username/DEV/rails-react-project/public' + file.path)
end
end
send_file zip_file_name
end
end
Note : I didn't tested code locally, so might give error. Comment on answer if you face error
Hope this helps!
I need to pass an array in a params, possible? Values can be, for example, ["1","2","3","4","5"] and these are strings but needs to eb converted to integers later.
I use a react_component in between a rails form_for. The html is like this:
<input type="hidden" name="people_id" id="people_id" value={this.state.people} />
The people array looks like this:
How can I pass the array in the value of the hidden field? The server error I got was
Im trying to do something like this in a model:
ids = params[:people_id]
ids.map do |b|
Foo.create!(people_id: b.to_i)
end
If I ids.split(",").map I get symbol to int error.
Edit:
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Still not sure what the issue is as nothing works. Here is a minimal reproduction of my code:
This answer is my react component and that's how I add to the array. Still in the component, I have the hidden field:
<input type="hidden" name="[people_id][]" id="people_id" value={this.state.people} />
_form.html.erb:
<%= form_for resource, as: resource_name, url: registration_path(resource_name), :html => { :data => {:abide => ''}, :multipart => true } do |f| %>
<!-- react component goes here -->
<%= f.submit "Go", class: "large button" %>
<% end %>
The story is, guest can select few people during registration in one go. Those people will be notified when registration is complete. Think of it as "I am inviting these people to bid on my tender". Those numbers, in the array, are user_ids.
users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
# POST /resource
def create
super do |resource|
ids = params[:people_id].pop # logs now as "people_id"=>["1,2"]
resource.save!(ids.split(",").map |b| Foo.create!(people_id: b.to_i) end)
end
end
end
New error on line resource.save:
no implicit conversion of Symbol into Integer
Edit #2
If I only have, in the create method:
ids.split(",").map do |b|
resource.save!(Foo.create!(people_id: b.to_i))
end
It works! Foo is created two times each with the correct people_id.
Because I am creating more objects: Bar, I do not know how to do that in:
resource.save!(<the loop for Foo> && Bar.create!())
The flow must be:
Device creates the User
Foo is created with the loop
Bar is created
etc
It has to be done that way as an User object is created on the fly.
In Rails you use parameter keys with brackets on the end to pass arrays.
However you should not concatenate the values as a comma seperated list but rather send each value as a seperate param:
GET /foo?people_ids[]=1&people_ids[]=2&people_ids[]=3
That way Rails will unpack the parameters into an array:
Parameters: {"people_ids"=>["1", "2", "3"]}
The same principle applies to POST except that the params are sent as formdata.
If you want a good example of how this works then look at the rails collection_check_boxes helper and the inputs it generates.
<input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" checked="checked" />
<label for="post_author_ids_1">D. Heinemeier Hansson</label>
<input id="post_author_ids_2" name="post[author_ids][]" type="checkbox" value="2" />
<label for="post_author_ids_2">D. Thomas</label>
<input id="post_author_ids_3" name="post[author_ids][]" type="checkbox" value="3" />
<label for="post_author_ids_3">M. Clark</label>
<input name="post[author_ids][]" type="hidden" value="" />
Updated:
If you intend to implement you own array parameters by splitting a string you should not end the input with brackets:
<input type="hidden" name="[people_id][]" value="1,2,3">
{"people_id"=>["1,2,3"]}
Notice how people_id is treated as an array and the input value is the first element.
While you could do params[:people_id].first.split(",") it makes more sense to use the correct key from the get go:
<input type="hidden" name="people_id" value="1,2,3">
Also you don't really want to wrap the "root" key in brackets. Thats used in rails to nest a param key in a hash eg. user[name].
On a particular page in my website, there are a variety of potential URL parameters:
http://www.example.com/my_webpage?at=2014-01-01&page=5
Now I want a simple way to add a parameter to that like this:
http://www.example.com/my_webpage?at=2014-01-01&page=5&records=100
So I tried the following HTML with embedded Ruby:
<form action="<%= request.original_url %>" method="get"># of records <input type="text" name="records"/></form>
The problem is the resulting page that opens is:
http://www.example.com/my_webpage?records=100
Essentially, the old parameters get wiped away. What's an easy way to retain them? I could loop through the params hash and add hidden_tags (I'd have to selectively exclude params not part of the request params), but I would expect with such a common use case scenario there's a better easier way.
While there isn't an easy Rails way of doing this automatically, Rails does provide access to the request parameters through the request.query_parameters hash. So I simply needed to add this in the form:
<% request.query_parameters.each do |key, val|%>
<input type="hidden" name="<%= key %>" value="<%= val %>"/>
<% end %>
i have a hidden_tag like this in my form
<%= f.hidden_field :loc , {:multiple => true} %>
which renders to
<input id="business_loc" multiple="multiple" name="business[loc][]" type="hidden" style="color: rgb(175, 175, 175); " value="">
currently am setting the business_loc value as a comma seperated string hoping rails would recognize when submit the form. But this is the value i got on the server side
"loc"=>["80.22167450000006,13.0454044"]
instead
"loc"=>[80.22167450000006,13.0454044]
how do i set the correct value in hidden field, so rails can understand it correctly.
You need to use multiple hidden fields, one for each element of the array of values.
For example:
<input id="business_loc" multiple="multiple" name="business[loc][]" type="hidden" style="color: rgb(175, 175, 175); " value="80.22167450000006">
<input id="business_loc" multiple="multiple" name="business[loc][]" type="hidden" style="color: rgb(175, 175, 175); " value="13.0454044">
...if you need code to dynamically add these with JS, here's a jQuery example:
var field = $('<input id="business_loc" multiple="multiple" name="business[loc][]" type="hidden" style="color: rgb(175, 175, 175); " value="13.0454044">');
var form = $('#your-form-id');
form.append(field);
I've found text_area's to make things work without having to add a bunch of hidden forms. Just set the value of the text area to something that looks like [1,31,51,61] and it should work, assuming in your model you have serialize :var
I had this same problem recently. My solution was to handle it on the server side by simply splitting the array at the comma. In my case it looks like this:
# thing_that_has_many_objects.rb <-- showing custom setter method from the model because my example involves using a virtual attribute
# params[object_ids] = ["1,2,3,4,5"] <-- from the form - note the format of array with only one element
def objects=(object_ids)
split_array = object_ids[0].split(',')
split_array.each do |id|
self.objects.build(object_id: id)
end
end
I have a form like
<input name="url[0]" type="text" />
<input name="url[1]" type="text" />
<input name="url[2]" type="text" />
I would like to be able to access these like:
params[:url].each do |url|
# work
end
I know that if I remove the explicit index from the name, this will work, but I would prefer to keep the index in. Is this something supported by rails out of the box?
You need to modify your block like so:
params[:url].each do |index, url|
# work
end
params[:url] will be an hash like this:
params[:url]
=> {'0' => 'url-1', '1' => 'url-2', '2' => 'url-3'}
So you have to iterate over the hash like this:
params[:url].each do |key, value|
# work
end