I'm posting some form data in the request body. something like:
{
formField1Name: formField1Value,
formField2Name: formField2Value,
...
}
the form field names are not known! and the values can be of the type string|string[]. how can i describe that with swagger? i was not able to use additionalProperties properly:
parameters:
additionalProperties:
in: "body"
description: "list of form field results"
required: true
type: "string"
Related
the following
#ids.class
is being properly returned as Array
But when it is being used as values
<%= button_tag 'Top', value: #ids, type: :submit, name: :top %>
the params submitted are:
"top"=>"17515 30784 31614 32342 32362 31815 31813 32386 33004 32483 31750 32478 16331 11728"
which is a string.
> params[:top].class
String
Transforming via Array(params[:top]) only results in a single element
["17515 30784 31614 32342 32362 31815 31813 32386 33004 32483 31750 32478 16331 11728"]
Transforming via substitution of space with a comma, to then generate a proper array
params[:top].sub(" ", ",")
only handles the first space
"17515,30784 31614 32342 32362 31815 31813 32386 33004 32483 31750 32478 16331 11728"
Modifying the tag to value: #ids.to_s returns the same situation.
How can this be properly processed by the subsequent action as an array?
How can this be properly processed by the subsequent action as an array?
Unless you want to do some wonky parameter processing like params[:top].split(' ') you need to use multiple parameters in a form or query string to pass an array.
To pass array parameters in Rack (the CGI that Rails sits on top of) you need to pass multiple formdata pairs where the key ends with [].
foo[]=1&foo[]=2&foo[]=3
# resulting params hash
=> { "foo" => ["1", "2", "3"] }
This is actually processed the same way regardless if its passed in the query string or request body.
For query strings #to_query handles this automatically:
irb(main):004:0> CGI.unescape( { foo: [1,2,3]}.to_query )
=> "foo[]=1&foo[]=2&foo[]=3"
For forms you can just create hidden inputs:
<% values.each do |v| %>
<%= hidden_field_tag 'top[]', v %>
<% end %>
Max's answer is correct but will use n hidden form fields to generate the foo[]=1&foo[]=2&foo[]=3 response.
If you still want to use it with the button_tag input field you can do something like the following
# In your form file
<%= button_tag 'Top', value: #ids, type: :submit, name: :top %>
And then use it like that in your controller
# Use #split on the string params
params[:top].split
Example
"10 20 30".split => ["10", "20", "30"]
You can always pass a delimiter to split by on the #split method
#split documentation
Consider the following rails link:
search_path(:query => params[:query], type: params[:type], sort: params[:sort])
There is a lot of duplication here. Is it possible to define these parameters in an array and they pass into the link? Eg.
params: [:query, :type, :sort] # -> pass each into the link like "key: value"
I can't think of how you could do it exactly passing it as an array like you show, however you could do something like:
search_path(params.slice(:query, :type, :sort))
This will give you the same hash you're passing in. In my opinion, it's a little cleaner.
parameters = ActionController::Parameters.new(query: 'query', type: 'type', sort: 'sort', other: 'other')
=> {"query"=>"query", "type"=>"type", "sort"=>"sort", "other"=>"other"}
parameters.slice(:query, :type, :sort)
=> {"query"=>"query", "type"=>"type", "sort"=>"sort"}
This is what I am trying to do:
= form_tag(path) do
- #items.each do |i|
= fields_for "i[]", i do
%input.content{:name => "content", :type => "hidden"}
= submit_tag "Submit"
As you can see, I try to pass the value of all .content inputs from itemsto a path.
These are the parameters I get:
{"utf8"=>"✓", "content"=>"", "commit"=>"Submit"}
I'd expect something like this:
{"items": [
{
"id":1,
"content":""
},
{
"id":2,
"content":""
},
{
"id":3,
"content":""
},
] }
How do you create those POST requests in rails?
This is simpler than you've been trying to make it. You tend to only need fields_for if you have a set of fields for each of the nested models. here you just have a single hidden column, so I'd choose to just use a single hidden field eg:
= form_tag(path) do |f|
- #items.each do |i|
= f.hidden_field "items[#{i.id}]", value: i.content
= submit_tag "Submit"
Note: not bug-testing left as an exercise to the reader.
This will generate a set of parameters that map the id of the item vs the content eg: "items"=>{"38383285"=>"", "304713261"=>"Some content here", "547539357"=>"Some other content here"}
Which you can just iterate through to change the actual values however you like.
You have not provided any example of the actual structure of your models - so I am guessing how you would use that... you will need to (possibly heavily) modify the example below to meet your actual needs.
For one thing - given it's a hidden field - I have no idea what other model (and column) it is that you are trying to update. So lets pretend you have a second model called OtherItem that also has a content-field and maps to an Item via an item_id column. In that case, you'd do something like this:
def my_action
item_ids = params[:items].keys
items = OtherItem.where(:item_id => item_ids)
items.each do |item|
item.update(content: params[:items][item.item_id])
end
# other stuff here
end
I'm using nested attributes in may rails project but when I submit a form I get the _attributes as a hash of hashes not an array of hashes like it's said in the documentation, which means rails can't get the params for the new object.
{"utf8"=>"✓",
"authenticity_token"=>"oLy4lJyXBgKiUI+TlQgEGIRNLeNOG5WqiHLqYNiZYe1JXC7+/j02ZDsBAnVZCAgeUJw6B5iTXxkzV1XzUIDn+w==",
"form"=>{"title"=>"test 3", "questions_attributes"=>{"0"=>{"question_text"=>"hello what?"}}},
"commit"=>"Create Form"}
like in the code above :questions_attributes should have been an array not a hash with an element called '0'
the form code:
= form_for(setup_form(#form)) do |f|
= error_messages_for(f.object)
= f.label(:title, 'Title')
= f.text_field(:title)
= f.fields_for(:questions) do |q|
= q.label(:question_text, 'Question')
= q.text_field(:question_text)
= f.submit "Create Form", :class => "btn btn-lg btn-primary"
I think you have not read whole doc. From documentation
Nested attributes for an associated collection can also be passed in
the form of a hash of hashes instead of an array of hashes:
Member.create(
name: 'joe',
posts_attributes: {
first: { title: 'Foo' },
second: { title: 'Bar' }
}
)
has the same effect as
Member.create(
name: 'joe',
posts_attributes: [
{ title: 'Foo' },
{ title: 'Bar' }
]
)
The keys of the hash which is the value for :posts_attributes are
ignored in this case. However, it is not allowed to use 'id' or :id
for one of such keys, otherwise the hash will be wrapped in an array
and interpreted as an attribute hash for a single post.
Passing attributes for an associated collection in the form of a hash
of hashes can be used with hashes generated from HTTP/HTML parameters,
where there may be no natural way to submit an array of hashes.
This is default behavior of nested attributes. If you add more questions fields to the form, output will be as :
{"utf8"=>"✓",
"authenticity_token"=>"oLy4lJyXBgKiUI+TlQgEGIRNLeNOG5WqiHLqYNiZYe1JXC7+/j02ZDsBAnVZCAgeUJw6B5iTXxkzV1XzUIDn+w==",
"form"=>{"title"=>"test 3", "questions_attributes"=>{
"0"=>{"question_text"=>"hello what?"},
"1"=>{"question_text"=>"Hi"},
"2"=>{"question_text"=>"Hello"}},
"commit"=>"Create Form"}
I have passed dynamic content to the body of the email. But looking at the API docs the subject params only accepts a string and not an array.
Is there a way to pass a dynamic subject? I would like to pass the name of the recipient in the subject
I have the following right now:
m = Mandrill::API.new ENV['MANDRILL_APIKEY']
message = {
:subject=> template.subject,
:from_name=> template.name,
:from_email=> template.from + "#" + email_domain,
:to=>mails,
:global_merge_vars=> [
{ :name => 'IMAGE', :content => image_tag},
],
:html=>email_template,
:preserve_recipients => false,
:merge_vars => variables,
}
It seems that Mandrill reads merge variables in the subject as well. So it is as simple as adding *|SOME_VAR|* in your subject text and then passing it as a parameter in the merge_vars.
More details here.