Generate hidden form field data with rails button_to helper? - ruby-on-rails

Currently, i use the following code for passing params[:id] to line_items create
<%= button_to 'Add to Cart', { controller: 'line_items', action: 'create', id: brick }, class: 'green radius nice button', method: :post, remote: true %>
However, it will append the id param on url query which i didn't suppose button_to to do. What i want is passing the id param via hidden the form field. Can i do that in button_to or any workaround for this issue?

Starting with Rails 4.1.0, button_to has now the additional options :params which can receive a hash that will be transformed into hidden fields. For example:
button_to 'Send Invitation', invitation_path(user), params: {'user[email]' => user.email}
Will give :
<form action="/users/invitation" class="button_to" method="post">
<div>
<input type="submit" value="Resend">
<input name="user[email]" type="hidden" value="user#yahoo.com">
</div>
</form>

I have done something similar in a module of my project:
First, I added a form with a hidden field:
<%= form_tag({:action => 'my_action'}, :id=>"item_form", :method => :post, :remote=>true) do%>
<%= hidden_field_tag :item_id, 0%>
<% end %>
all mi items on the list will have a check_box_tag wich contains the item id:
<%= check_box_tag "item_ids", item.id, false,:id => item.id, :class => "my_fancy_class"%>
when an item is picked just catch the event, replace the value on the hidden_field and trigger the form:
function( event, ui ) {
$("#item_id").attr('value',ui.selected.id);
$('form#item_form').submit();
}
if you want to render stuff just add a action.js.erb file to your controller view folder, but thats another thing.

Related

Rails form_for sending params to controller action and not model

In the controller review_queue I have a custom action that posts a result to a target URL, I want to build a form for this action. I am not going to save any of the fields to the DB I am just going to pass them in the params to the post_review action.
def post_review
RestClient::Request.execute(:method => :post,
:url => Rails.application.secrets['target_url'],
:content_type => :json,
:payload => #result_params.merge!(params[:reasons]).to_json,
:headers => HEADERS)
end
In the view I have a form that will be filled out and on submit it should send up the reasons when the form is submited, I am setting the review_queue_id and the status in the form, since these are static, but the reasons should come from the textarea
<%= form_for(:review_queue, url: { action: 'post_review', :review_queue_id => #review_queue.id, :status => 'accepted'} ) do |f| %>
<div class='form-group'>
<label for='comment'>Please give a reason? (required)</label>
<%= f.text_area(:reasons, placeholder: 'Your commentns ...', rows: 9, class: 'form-control') %>
</div>
<div class='modal-footer'>
<%= f.submit 'Approve', class: 'btn btn-success btn-decission btn-modal-left-side' %>
<button type='button' class='btn btn-default' data-dismiss='modal'>Close</button>
</div>
<% end %>
error message:
NoMethodError - undefined method `reasons' for #<ReviewQueueApplication:0x007fa7ff7832d8>:
It seems as if rails is assuming the MVC architecture here, and assuming I want to pass the reasons to the review_queue model. there is no reasons column so it's dropping a no method error. Is there a way of specifying that the form is 'temporary' and only getting as far as the controller?
This seems like it should be a simple thing but there is some rails magic happening here.
NoMethodError - undefined method `reasons' for
ReviewQueueApplication:0x007fa7ff7832d8
form_for assumes that you are creating a form for a model object and expects the fields to be present in that specific model's table(in a normal situation).
You should be going with form_tag
<%= form_tag post_review_path, method: :get, :review_queue_id => #review_queue.id, :status => 'accepted'} ) do |f| %>
<div class='form-group'>
<label for='comment'>Please give a reason? (required)</label>
<%= text_area_tag(:reasons, placeholder: 'Your commentns ...', rows: 9, class: 'form-control') %>
</div>
<div class='modal-footer'>
<%= submit_tag 'Approve', class: 'btn btn-success btn-decission btn-modal-left-side' %>
<button type='button' class='btn btn-default' data-dismiss='modal'>Close</button>
</div>
<% end %>
And in the controller access it like params[:reasons]. Also if you noticed, I've added method: :get to the form_tag as you don't want to save the info to DB
The rails helper form_for is used for forms for rails resources. You want to use the form_tag helper. Search for form_for and form_tag here for more information on these 2 methods.

Rails search URI with unwanted parameters?

Background
I am creating a search field in my header. This code in my view:
<% if signed_in? %>
<%=f orm_tag( "/search", method: "get", :class=>"navbar-form navbar-left", :role => "search") do %>
<div class="form-group">
<%=t ext_field_tag :q, nil, :class=>"form-control", :placeholder => 'Domain/IP Search' %>
</div>
<%=b utton_tag "Search", :type=>'submit', :class=> "btn btn-primary" do %>
<span class="glyphicon glyphicon-search"></span>
<% end %>
<% end %>
creates this output:
<form accept-charset="UTF-8" action="/search" class="navbar-form navbar-left" method="get" role="search">
<div style="display:none">
<input name="utf8" type="hidden" value="✓">
</div>
<div class="form-group">
<input class="form-control" id="q" name="q" placeholder="Domain/IP Search" type="text">
</div>
<button class="btn btn-primary" name="button" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</form>
Here is a picture:
The issue
The problem is when I search, I get this in my url:
/search?utf8=✓&q=test&button=
Ideally, I'd like it to be more like:
/search?q=test
tl;dr:
How do I get rid of the button parameter (and hopefully the utf one as well).
Extra info:
routes.rb
resources :search
search_controller.rb
class SearchController < ApplicationController
def index
#results = params[:q]
puts #results.to_s
end
end
search\index.html.erb
<%=#results.to_s %>
EDIT, answer
Adding this because while the accepted answer helped me get to the solution; it didn't have the exact code for my circumstance. I made these changes:
1) routes:
match '/search', to: 'search#index', via: 'post'
2) form in my header:
<%= form_tag search_path, method: "post", :class => "navbar-form navbar-left", :id=> "SearchForm", :role => "search" do %>
<div class="form-group">
<%= text_field_tag :q, nil, :class => "form-control", :placeholder => 'Domain/IP Search' %>
</div>
<%= button_tag "Search", :type=> 'submit', :class=> "btn btn-primary" do %>
<span class="glyphicon glyphicon-search"></span>
<% end %>
<% end %>
GET
The bottom line, as I wrote in another answer, is that you're using GET:
Essentially, when you submit a GET form, it appends the parameters to your URL, whilst a POST form will append the data to the request body (or somewhere hidden).
The difference is just that the GET request expects a response to be returned immediately, and so you have to pass the parameters in the URL to ensure the server knows how to construct it. The best example being if you use a GET request to load a page.
The POST method is used primarily used for forms, where a response is not expected immediately; thus allowing you to keep the params hidden in the request.
Fix
We've actually created a basic search feature here (the actual search doesn't work for some reason, but the live search does)
The way we did it was as follows:
match 'search(/:search)', :to => 'products#search', :as => :search, via: [:get, :post]
This will firstly allow you to access the search action by typing domain.com/search/your-query-here
In terms of submitting via a form, you'll be able to use JQuery to amend the URL with the input from the text field:
#app/views/elements/_nav.html.erb
<%= form_tag search_path, :method => :post, :id => "SearchForm" do %>
<%= text_field_tag :search, params[:search], placeholder: 'Search your favourite products or brands', :autocomplete => :off, :id => 'SearchSearch' %>
<%= image_submit_tag('nav_bar/search.png', title: 'Search', class: 'search_submit', data: { "placement" => "bottom" }) %>
<% end %>
#app/assets/javascripts/application.js
//Search Submit
$(document).ready(function() {
$('#SearchForm').submit(function(e) {
e.preventDefault();
if( $('#SearchSearch').val().length > 0 ) {
var search_params = '/' + $('#SearchSearch').val().toLowerCase();
}else{
var search_params = ''
}
window.location.href = $(this).attr('action') + search_params
});
});
If you are not doing with the Utf8 parameter but, Rails is & but its needed. It's to correct some issues in IE's parameter encoding, This parameter was added to forms in order to force Internet Explorer 5, 6, 7 and 8 to encode its parameters as unicode.Its fixes encodeing issue of IE.
Please refer following link:
What is the _snowman param in Ruby on Rails 3 forms for?
This parameter is a feature of rails.
It was previously the snowman.
It helps IE to really use utf-8.
Avoid using form_tag and it works:
<form action="<%= search_path %>" method="get" >
<%= text_field_tag 'query' %>
<%= submit_tag "Search", :name => nil%>
</form>
Now style your form as you want

validation on simple form in ruby on rails

I have a simple_form which is not tied to an object. I am using parameters such that whenever i submit a form, it gives parameters to create method in posts controller. Same as form_for_tag.
<%= simple_form_for :postFoo, url: {controller: 'posts', action: 'create', user_id: "#{current_user.id}", group_id: "#{#group.id}" } do |f| %>
<div style="float:left"> <%= f.input :bulletin_post, label: false, placeholder: 'Create new post ...' %> </div>
<div style="float:left"> <%= f.submit "Post", class: "btn btn-warning btn-sm" , id: "bulletinSubmit" %> </div>
<%end%>
Post Controller, create method:
#post = Post.create(user_id: params[:user_id], bulletin_post: params[:postFoo][:bulletin_post], group_id: params[:group_id])
My question is, how to validate the :bulletin_post input field to be non-empty before submitting ? This would be simple if it was directly tied to an object using model validation.

Is it possible to make a link that functions as same as form does?

Now I have 2 forms that submit a comment.
Form Type A
<%=form_for(([#community, #comment]), :remote => true, :class => 'form' ) do |f| %>
<%= f.text_field :body, :id => "body", :class => "chat" %>
<button type="submit" class="btn">submit</button>
<% end %>
Form Type B
<%=form_for(([#user, #comment]), :remote => true, :class => 'form' ) do |f| %>
<%= f.text_field :body, :id => "body", :class => "chat" %>
<button type="submit" class="btn">submit</button>
<% end %>
Now, I want to have link_to button that functions as same as those forms do if a user clicks it.
When the user click on the link, #comment will be automatically filled just like below.
From Form Type A
#comment = "this is for community"
From Form Type B
#comment = "this is for user"
How can I do that? As far as I understand my situation.
Form is put type, then link_to is get type so it's impossible to re-use transaction of form.
Not sure what you mean by "transaction of form" but if you're asking if you can create/modify data via a single button or link than the answer is Yes, it is possible.
You can actually put with a link_to in rails ({:method => :put} (http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to)
If you want a button to do this you should checkout button_to (http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to)
It's better to use button_to.

Getting a form to use :method => :delete (rails)

I have a cart which contains many line_items. I'd like to have a "delete" button next to each line item that, upon clicked, removes the line_item from the cart.
I know I can do this with a button_to method, but I'd like to use form_for because I'd like to change the attributes of the line_item's parent object at the same time (each line_item also belongs to a course, and I'd like to tell the course parent that it's no longer in the cart).
Here's my code using form_for:
<%= form_for(line_item, :method => :delete, :remote => true) do |f| %>
<%= f.submit :value => "Delete" %>
<% end %>
The ruby documentation says that simply adding :method => :delete should work (http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for), but the rendered html isn't quite right. It's still
<input name="_method" type="hidden" value="put">
But it should be:
<input name="_method" type="hidden" value="delete">
What am I doing wrong?
Mark Needham has a blog post that talks about why :method => delete in form_for doesn't work. He says
It turns out that ‘form_for’ expects the ‘:method’ to be provided as part of the right hand
most argument as part of a hash with the key ‘:html’.
So you need to change your code from:
<%= form_for(line_item, :method => :delete, :remote => true) do |f| %>
to:
<%= form_for(line_item, :html => { :method => :delete, :remote => true }) do |f| %>
I tried it in a Rails 3.0 application, and the generated HTML was:
<input type="hidden" value="delete" name="_method">
Mine in HAML is just:
= form_with url: destroy_user_session_path, method: :delete do |form|
= form.submit "Sign out"

Resources