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.
Related
I'm fairly new to Rails and I'm stuck with passing a text field value to Rails Controller method. Any help is appreciated, below is my code..
View code:
Upon click of the below button I want to be able to send the username to the Controller method..
<%= link_to "My button", admin_user_creds_path(user_config),
method: :test_user, role: "button" %>
The username is entered in a text field:
<%= form_for [:admin, user_config] do |f| %>
<td class="js-editable-text rf-table__td rf-table__col--username">
<div class="preview js-preview show"><%= user_config.username %></div>
<div class="js-input hide"><%= f.text_field :username, class: "form-control" %></div>
</td>
My routes file:
post "/user_configurations/:id", to: "user_configurations#test_user", as: "user_creds"
My controller:
def test_user
username = user_params[:username]
end
def user_params
params.require(:user_configurations).permit(:username)
end
Instead of using link_to helper you need add a submit button to your form.
<%= form_for [:admin, user_config] do |f| %>
<td class="js-editable-text rf-table__td rf-table__col--username">
<div class="preview js-preview show"><%= user_config.username %></div>
<div class="js-input hide"><%= f.text_field :username, class: "form-control" %></div>
<%= f.submit "My button" %>
</td>
Also please note that method option in link_to helper is either get or post HTTP methods but not the controller action
EDIT 2
Related question here.
EDIT
This is the route I need to submit to:
get '/s/:term', controller: :products, action: :search, as: :search_products
I have a search form like this:
<%= form_tag(search_products_path, :method => "get", id: "search-form", name: "f1", enforce_utf8: false) do %>
<div class="input-group">
<%= text_field_tag :search, params[:search], placeholder: "Search products", class: "form-control", name: "search" %>
<div class="input-group-btn">
<button class="btn btn-secondary">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
</div>
<% end %>
But this creates the url like this:
domain/s?search=[user input]
I need the URL to be like this instead:
domain/s/[user_input]
Yes I do know this is not following Rails convention. I couldn't care less at this point, I just need to figure it out.
Thanks.
There's no way to do this using just form_tag, since the url that the form submits to needs to be dynamic. But it can be done using javascript:
$("#search-form").submit(function(evt) {
var term = $("#search-form input[name='search']").val();
$(this).attr('action', '/s/' + encodeURIComponent(term));
});
This will result in the form submitting to: domain/s/[user input]?search=[user input]
You could further prevent the ?search= parameter from being included in the url by omitting the name attribute from the field (see https://stackoverflow.com/a/3008071/157943), though then you'd need to give it an id or some other way for the javascript snippet above to locate it.
Thanks to the comments from #TarynEast and the other question linked in my second edit, I realised I was very confused - so thank you Taryn!
This has to be done in 2 separate actions/routes, like this:
post '/s', controller: :products, action: :search, as: :search_products
get '/s/:search', controller: :products, action: :index, as: search_results_path
Whatever the user inputs is then posted by the form to that search action.
Here is the form:
<%= form_tag(search_products_path, :method => "post", id: "search-form", name: "f1", enforce_utf8: false) do %>
<div class="input-group">
<%= text_field_tag :search, params[:search], placeholder: "Search products", class: "form-control", name: "search" %>
<div class="input-group-btn">
<button class="btn btn-secondary">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
</div>
<% end %>
The products#search action simply does a redirect:
def search
# ORIGINALLY: redirect_to "/s/#{params[:search]}"
redirect_to search_results_path(params[:search])
end
Then we can extract the :search param and use it to search the model, like so:
def index
if params[:search] && !params[:search].blank?
#products = Product.search params[:search]
...
etc
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.
I'm playing with the messenger gem in rails 4.
I have a graph of nodes and I want to be able to bring up a message box (initially in a different page but will make it a partial later) when a node is pressed so that the current user can message that node.
The id for the clicked node is kept in a div called NameID
At the moment all I've got working is a button that opens the new message page and then you can choose a user from a drop down list. I guess I want that drop down list- the recipient- to be prepopulated from the currently clicked node on the index page.
Here is what I have so far:
index.html.erb
<p><a class="btn btn-lg btn-primary" id="BtnMessageNode" href="/messages/new">Start conversation</a></p>
<div id=NameID><<THIS IS POPULATED BY JAVASCRIPT>></div>
messages_controller.rb
class MessagesController < ApplicationController
before_action :authenticate_user!
def new
#chosen_recipient = User.find_by(id: params[:to].to_i) if params[:to]
end
def create
recipients = User.where(id: params['recipients'])
conversation = current_user.send_message(recipients, params[:message][:body], params[:message][:subject]).conversation
flash[:success] = "Message has been sent!"
redirect_to conversation_path(conversation)
end
end
helpers/messages_helper.rb
module MessagesHelper
def recipients_options(chosen_recipient = nil)
s = ''
User.all.each do |user|
s << "<option value='#{user.id}' data-img-src='#{gravatar_image_url(user.email, size: 50)}' #{'selected' if user == chosen_recipient}>#{user.name}</option>"
end
s.html_safe
end
end
messages/new.html.erb
<% page_header "Start Conversation" %>
<%= form_tag messages_path, method: :post do %>
<div class="form-group">
<%= label_tag 'message[subject]', 'Subject' %>
<%= text_field_tag 'message[subject]', nil, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= label_tag 'message[body]', 'Message' %>
<%= text_area_tag 'message[body]', nil, cols: 3, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= label_tag 'recipients', 'Choose recipients' %>
<%= select_tag 'recipients', recipients_options(#chosen_recipient), multiple: true, class: 'form-control chosen-it' %>
</div>
<%= submit_tag 'Send', class: 'btn btn-primary' %>
<% end %>
There are basically two ways to pass parameters to GET routes:
A. Named segments
/users/:user_id/message/new
This nested route would be great if you are sending a message to a single user.
B. Query parameters
Rails supports query parameters as well:
/message/new?to=2
Rails automatically adds query parameters to the params hash. So in this case you would do params[:to].
You can use the Rails route helpers so that you don't have to deal with encoding urls yourself:
new_message_path(to: #user.id)
Use query params for optional parameters like filters and sorting or in this case a preset. Don't use them like users?id=5.
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.