Rails 5 simple search form just won't work - ruby-on-rails

I have a navbar shared across all views by rendering it in application.html.erb with this form in it:
<form class="form-inline d-none d-lg-inline-flex">
<%= form_tag search_query_path, method: :get do |f| %>
<%= text_field_tag :query, params[:query], class: "form-control", placeholder: "Search" %>
<%= submit_tag "Search", name: nil %>
<% end %>
</form>
I want to search for similar titles in the Post model.
The methods are in the PostsController as follows:
def search_query
#results = Post.find_by_sql("SELECT * FROM posts WHERE title LIKE '%#{params[:query]}%'")
end
def search_query_params
params.require(:post).permit(:query)
end
private :search_query_params
The problem is: the search keeps getting processed by the current controller of the current view. If I'm the the index page (in the PagesController), the query takes place there, just reloading the url like this:
http://localhost:3000/?utf8=%E2%9C%93&query=test+title
I've tried everything and can't find where my logic is wrong.
These are the routes:
get '/search_query', to: 'posts#search_query', as: 'search_query'

form_tag generates a form element, so you are nesting a form inside a form here. Try deleting the outer form.

Related

Rails form_tag not displaying the existing field value

I've a settings controller setup like this:
class Admin::SettingsController < ApplicationController
def index
#settings = Setting.all
end
def update
setting_params.each do |key, value|
Setting.where(key: key).first.update_attribute :value, value
end
redirect_to admin_settings_path, notice: "Settings saved."
end
private
def setting_params
params.require(:settings).permit(:site_title, :site_desc)
end
end
The index action has a view file in relevant path, its code is as follows:
<h1>Settings</h1>
<%= form_tag admin_settings_path, method: "put" do %>
<p>
<label>Site Title:</label>
<%= text_field_tag "settings[site_title]" %>
</p>
<p>
<label>Site Description:</label>
<%= text_field_tag "settings[site_desc]" %>
</p>
<p>
<%= submit_tag "Save settings" %>
</p>
<% end %>
Now, I'm able to save/update these fields data in relevant model and I can see the data through command Setting.all in rails console. But the issue is, after saving the record via form when I reload the settings index page the form is blank and it is not showing previously saved values in the fields.
What I'm doing wrong here?
You can do what has been mentioned in the previous answer i.e. using a form_for. However, this can also be accomplished by creating a Hash in both the controller actions that creates and processes this form.
In the action that creates this form, the values in the hash could be initialized to blanks/zeros depending upon the input tag and in the action that processes this form, the values in the hash could be assigned to the values obtained from the posted params[].
I ran into the similar issue with form_tag and I used the following code in my index action i.e. the action that renders the form initially:
#search = {name: "", ranking_group: 0}
Whereas, in the search action, I used the following code to fill up this hash:
#search = {name: params[:name], ranking_group: params[:ranking_group]}
Finally, in the view, I used the appropriate default value options with the input tags as below:
<%= text_field_tag :name, #search[:name] %>
<%= select_tag :ranking_group, options_for_select(AmenityEntities::Amenity.ranking_group_options, #search[:ranking_group]), include_blank: true %>
Hope this helps.
I think you need to use form_for(#variable) instead of just a form_tag because you need to persiste the object after save.
form_for works with resources, take a look here: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html

Rails search form in different controller?

Okay say I have a simple search form for Projects records like in the railscast found here: http://railscasts.com/episodes/37-simple-search-form?autoplay=true
Can you put the form_tag for the search in a different view other than the projects index.html? Like in a static_pages controller type of deal view? And how could you redirect to the projects index.html view after submitting the search in such a case? Thanks
Add below code wherever you want to add search functionality.
<% form_tag projects_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
Changes needed in your controller only. Try render view instead of redirect and you are done.
def index
#projects = Project.search(params[:search])
render `projects/index`
end

Rails, form that can work with different controllers

I want to make erb template of searchbar that will call search method of its controller. Different controllers got same method, but will have different logic. Is it possible to make form that will work with every controller just by rendering it on their views?
--- UPDATE ---
I have found that kind of solution:
<%= form_tag "#{controller_name}/search", method: 'get' do %>
<div class="input-group">
<%= text_field_tag :sub_string, '', class: 'form-control', placeholder: "Search..." %>
<span class="input-group-btn">
<%= submit_tag 'Search', class: %w(btn btn-primary) %>
</span>
</div>
<% end %>
However when I hit the submit button, it goes to search action of my current controller and it thows an error:
Couldn't find Basis with 'id'=search
it tries to call set_basis private method, even if it is not called by before_action?
Set search form's controllers name with params[:controller].
Use Rails Guide to see how to pass controller and action for a form_tag or form_for.
I think you can
create the template/partial under views/shared folder
then in controller do something like
def search
render :partial => "shared/search"
end
Ok Then add this
in your partial so you can dynamically change your controller for the form
form_tag({controller: controller.controller_name, action: "search_action"}, method: "post", class: "form")

How do I pass a parameter to a form partial that is shown via CSS?

So my form partial is loaded in my div id="secondary", which is hidden on first page load.
When the user hits a button with a class called toggleSidebar, then the _form.html.erb is shown.
I have overridden the partial to display a new form (even if update is pressed) when a user is not logged in like this:
<%= simple_form_for(Post.new, html: {class: 'form-horizontal' }) do |f| %>
As opposed to the regular version that looks like this, and is included in an if statement on this same partial:
<% if current_user and current_user.has_any_role? :editor, :admin %>
<%= simple_form_for(#post, html: {class: 'form-horizontal' }) do |f| %>
The real issue is in my view, when someone goes to Update, this is what happens when the user is logged out:
<%= link_to "Update", "#", class: "togglesidebar" %>
This is perfect, it executes the CSS and shows the empty form partial perfectly.
However, when a user is logged in, I want it to send the parameter parent_id: #post with the execution of the sidebar being toggled.
This is how it looks with a normal new_post_path view (i.e. the non-sidebar new post view):
<% if current_user %>
<%= link_to "Update", new_post_path(parent_id: #post) %>
<% end %>
This is what my PostController#New looks like:
def new
#post = Post.new(parent_id: params[:parent_id])
end
How do I either pass the params in the regular non new_post_path version, or tackle this another way?
You could probably use a helper method.
Just browse to the 'helper' directory under 'app' folder and create a file similar to [name]_helper.rb
In this file create a module by [name]Helper and declare your helper method in this module.
This module is automatically required by rails.
A small example might help you.
The code in the link_helper.rb under app/helper directory
module LinkHelper
def populate_link(link1, link2, parameter)
if current_user
public_send(link2, parameter)
else
link1
end
end
end
The code in views is
<%= link_to 'update', populate_link('#', 'new_requirement_path',parameter: 33) %>
I'm a bit confused by the question, but I think you may be just need to use a hidden field to pass the parent_id param back?
e.g./
<%= simple_form_for(Post.new, html: {class: 'form-horizontal' }) do |f| %>
<%= f.hidden_field :parent_id, { value: #post.try(:id) } %>
<% end %>
HTH?
I am also a bit confused, but the following railscast might help you. It shows how to embed data in an html-tag. You can probably do it the same way.
railscast-> passing data to javascript
Out of the possibilities there I'd recommend the data-attribute:
<%= simple_form_for,(Post.new, html: {class: 'form-horizontal' }, **data: {post_id: #post.id}**) do |f| %>
<% end %>

Rails Controllers - Adding a Custom Action

I have an Article resource and have defined resourceful routes for it. I want to create a simple page that shows the articles of the current user. I am aware that it is possible to do so by adding another action, for example 'search' to articles controller which will contain the custom code that searches for articles that have the same user id. And for the routes:
resources :articles do
get 'search'
end
But I'm not sure if adding a custom action is a good idea in this case. I'm thinking I can still use the index action (which shows all articles) and pass some sort of parameter from the url so that it can distinguish if the user wants to see all articles or just his own. But I'm not sure exactly how this can be done. Any help would be great. Thanks!
You can use the query string to pass parameters. see here
So you can pass something like .../articles?user_id=2
In your controller, just change the behavior according to the user_id parameter.
you don't need to create a new action/view for it.
You can add a small form to filter all articles or only my articles, for example:
<%= form_tag articles_path, method: :get do %>
<%= radio_button_tag :search, "all", :checked => true %>
<%= label_tag :all %><br />
<%= radio_button_tag :search, "my" %>
<%= label_tag :my_articles %><br />
<%= submit_tag "filter", name: nil %>
<% end %>
than in your controller:
def index
if params[:search] == 'my'
#articles = current_user.articles
else
#articles = Article.all
end

Resources