Submit form on ID of RESTful route without persistent object - ruby-on-rails

Rails 3.2.0 | Ruby 1.9.2
Route:
xyz_catalog_device_info
GET|POST /xyz/catalog/devices/:device_id/info(.:format)
xyz/catalog/devices#info`
My app wraps up several API services into one system to provide a single place to maintain SSL Certificates and complicated XML generation logic. My controller makes an HTTP call to a 3rd party API to obtain the information, so there's no XYZ::Catalog::Device persisting (no #device) to implement the usual rails form helper tricks.
I want to create a form like the following:
%form{ :action => xyz_catalog_device_info_path(:format => :xml) }
= label_tag :device_id, "Device ID:"
= text_field_tag :device_id
= submit_tag "Search"
so that it will fill in the device_id in the action.
Is this possible without using javascript? Is there a better way of doing this?

Sounds like what you are looking for is http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html
Where you would just use soemthing like...
= form_tag(xyz_catalog_device_info_path(:format => :xml)) do
= label_tag :device_id, "Device ID:"
= text_field_tag :device_id
= submit_tag "Search"

Related

Rails - Merge Multi-Select Params into comma-separated string

I have a select box that allows multiple values, to filter the results on the page. When I select multiple, the Parameters that are submitted look like this:
Parameters: {"categories"=>["books", "films"], "commit"=>"Submit", "id"=>"87"}
When I am returned to the page, the URL is:
http://localhost:3000/87/projects?categories%5B%5D=books&categories%5B%5D=films&commit=Submit
The URL I would like to return is:
http://localhost:3000/87/projects?categories=books,films
How can I return these params[:categories] as a comma-separated string in the URL? Also, is it possible to remove the "&commit=Submit" from the URL?
Here is my full form code:
<%= form_with url: project_path(#project), local: true, method: :get, skip_enforcing_utf8: true do |form| %>
<%= form.select(:categories, #categories.map {|category| [category.name,category.slug]}, options = { selected: params[:categories], include_blank: "Select Categories", include_hidden: false }, html_options = { multiple: true }) %>
<%= form.submit 'Submit' %>
There's a couple JS & Rails way to do what you want. I can think of a quick and easy one using rails only: Redirecting the URL you are getting to another route with the data parsed as you want it. Like this -->
Assuming this is your route to project_path : get 'project', to: 'project#reroute', as: :project
You can go to your reroute method in the project controller and parse the data you got.
project_controller.rb
class ProjectController < ApplicationController
def reroute
redirect_to your_path(categories: params[:categories].join(','))
end
end
This converts your categories array to a string with your values separated by commas. It is not an array anymore. and it also removes "&commit=Submit" like you wanted.
If you dislike the rails routing method, you can also make your submit button to run some JS functions that builds the url string as you want it. For example <%= submit_tag , :onclick => "return buildUrl();" %>
Having this said, I must say I agree with Edward's comment, the url encoded format is standard and works out of the box, no need for all the additional rerouting and parsing. Im pretty sure whatever you need the data for can be used with the URL encoded format with proper parsing.

text_field_tag with ActiveAdmin

I've a hard time with ActiveAdmin and their DSL. I'm using it to build my admin and at some point in a form I need to have a text_field_tag; I mean some fields which aren't related to the model I'm manipulating in the form which will be sent through with the model related data.
A custom text field basically. Nothing too crazy.
So I've built this
panel 'Send payment authorization' do
active_admin_form_for EventPaymentAuthorization.new, url: { action: :send_event_payment_authorization } do |f|
f.inputs do
f.input :body, as: :text
f.text_field_tag :line_items_label
f.text_field_tag :line_items_amount
f.input :fees_in_cents, as: :select, collection: [:free, :automatic], prompt: true, selected: :automatic
end
f.actions do
f.action :submit, label: 'Create payment authorization'
end
end
end
The f.text_field_tag get simply ignored by ActiveAdmin. Why is that? It doesn't raise any error, but it doesn't show either.
The reason I need custom unrelated inputs is because line_items in my example is a JSONB with values such as [{amount: 0.0, label: 'Hello'}] and I don't believe it can be processed through Formtastic or ActiveAdmin natively. It's also always good to be able to create custom inputs when sending data.
Working with JSON in ActiveAdmin is a bit tricky, it largely depends on your needs. The quickest way to get going is to use the activeadmin_json_editor gem. I also wrote a blog entry on working with JSON in ActiveAdmin with more detail and another approach, which may better suit your needs, as it appears you are not just working with arbitrary data into your JSON field.

Cannot pass parameters to controller

I have the following haml code in index.haml
%h1.content-header{id: 'content-header'} HEADER
%section.form
%form.standard{action: some_path, method: 'get'}
%fieldset.search{'aria-labelledby' => 'content-header'}
%input{type: 'search', name: 'name', placeholder: 'something', role: 'textbox'} -----(6)
%fieldset.input-actions
%input.primary-action{type: 'submit', value: 'search' , name: 'invokeSearch'}
I have the following in my controller
def index
Rails.logger.debug "#{params[:name]}"
unless #invalid_characters
unless params[:name].blank?
....
....
....
The issue is if i change the name: 'name' in line 6 to say name: 'test' .... params[:test] is always blank in my controller. But if i use name: 'name' , params[:name] seems to work . No clue what i am doing wrong here
If you are using rails you should probably benefit from using one of the form helpers for generating the form. For example forms_for that makes you access things in your model directly. It may look like this.
= forms_for #thing do |f|
= f.text_field :name
= f.text_field :test
= f.submit
In this case there will be a map for the model instance in the params map. Something like
params[:thing][:name]
or
params[:thing][:test]
you can take that map and pass it into a model to create or update it. If you don't want the tight coupling with the model there is the form_tag method that does much the same thing except you need to be more explicit in what value goes where. And fields ends up directly in params instead of in a model hash.
To see how your params come in you can use the inspect method.
puts "params: #{params.inspec}"
or install pry to set a break point with
binding pry
Some ideas. Hope it works out for you. I think you should start with trying to use the rails forms helpers and it will probably sort itself out.

Formtastic non-model form, integration with external site, override/specify the input ID values

I'm using formtastic to collect information from a form and post dirctly to an external site.
I have no problem generating the form itself. However, since this is being submitted to an external site, they require that each input field have the specific IDs they specify, eg email or last_name -- not the closest Formtastic form, eg _email_input or _last_name_input.
I've looked at the Formtastic v1.2.3 code and I'm 90% sure the answer is "sorry, can't do that." I figured it couldn't hurt to check if I'm missing something. I would like some way to specify the ID completely, as in:
= semantic_form_for('', :url => "https://external_site.com/handler, :method => "post") do |form|
= form.input :last_name, :id => "last_name"
[etc]
Is this possible?
(I will note that I recognize that another, arguably superior approach would be to create an appropriate controller, sanity check the parameters locally, and dispatch the remote call from within the app only when it's well formed; however, that's not what I'm trying to do at the moment.)
Firstly i think you need to use semantic_fields_for for non-model forms. Next, to pass ids to each field, you can use the input_html options to specify them. for eg
form.input :email, :input_html => {:name => 'email', :id => 'email' }

Generating unique HTML ids in Rails when using a repeated partial that has form_for

I have a view on my current project which does something like the following(in haml):
-#horses.each do |horse|
= render :partial => 'main/votingbox', :locals => {:horse => horse}
The in the _votingbox.html.haml file I have the following:
%div.votingbox
%span.name= horse.name
%div.genders
- if horse.male
%img{:src => 'images/male.png', :alt => 'Male'}
- if horse.female
%img{:src => 'images/female.png', :alt => 'Female'}
%div.voting_form
= form_for(Vote.new, {:url => horse_vote_path(horse)}) do |f|
= f.label :comment, "Your opinion"
= f.text_field :comment
...
a bunch of labels and input elements follow generated using the form helpers
This will generate working code but it does generate forms with the same ids for all the form elements which makes the HTML invalid once the votingbox partial is rendered a second time.
My first guess at fixing this was to specify a unique :id to form_for but that only applies to the form tag generated by form_for and not any of the tags inside the form_for block.
One definite solution to this problem is to go through and manually define my own unique ids on form_for and all the form elements I use. This is more work than I had hoped for.
Is there an easier or cleaner way to get unique ids in a similar format to the way Rails currently generates them on all my form elements?
I have removed the original answer as it is totally irrelevant to the updated version of the question.
Update: So now we know that you have an unsaved ActiveRecord object passed to the form_for call, the answer becomes simple: You can override any parameter that form_for generates. That includes the element id. And fields_for sets the context for a specific record.
= form_for(Vote.new, :url => horse_vote_path(horse), :id => dom_id(horse, 'vote')) do |f|
= f.fields_for horse, :index => horse do |fh|
= fh.text_field :whatever
…
You can override the autogenerated ids and names of all form_for content with :as like the following:
= form_for(Vote.new, :as => horse.name, {:url => horse_vote_path(horse)}) do |f|
= f.label :comment, "Your opinion"
= f.text_field :comment
So if a given horse.name is foobar, it will generate a comment field whose id is foobar_comment and name is foobar[comment]
But remember to make sure that the dynamic parameter is acceptable as an html id, a horse.name like hor$e is not acceptable as an html id and therefore might break something.
P.S: Sorry for answering very late, but at the time the question was asked, I haven't had learnt anything at all about rails! hope that might help someone out there!

Resources