I am using elasticsearch on my rails 4 app to search through my articles.
However, when an article is not found it redirects to a page where it alerts the user that no results are found, and allows to request a page. Instead of it saying "no results found" I want it to say "no results for ______ found" in which is takes the search bar query.
I have defined a method in the articles_controller in order to get the query but it won't show up on the page since the "no results page" uses a different controller.
What would be the best way to pull the method onto another controller or view in this case? Having trouble finding a straight forward answer for what I am trying to do. Thank you very much.
articles_controller:
def index
if params[:query].present?
#articles = Article.search(params[:query], misspellings: {edit_distance: 1})
else
#articles = Article.all
end
if #articles.blank?
return redirect_to request_path
end
get_query
end
private
def get_query
#userquery = params[:query]
end
new.html.erb (view for "no results found" page. Uses a different controller than articles page):
<body class="contactrequest">
<div class="authform" style="margin-top:15px">
<%= simple_form_for #request, :url => request_path do |f| %>
<h3 style = "text-align:center; color:red;">No results found. <%= #userquery %></h3>
<h1 style = "text-align:center; color:black;">Request a Page</h1>
<h5 style = "text-align:center; color:black; margin-bottom: 25px;">Our experts will gather the information,<br> and have your page us ASAP!</h5>
<%= f.error_notification %>
<div class="form-group">
<%= f.text_field :email, placeholder: 'Email', :autofocus => true, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.text_field :subject, placeholder: 'Item / Page Requested', class: 'form-control' %>
</div>
<div class="form-group">
<%= f.text_area :content, placeholder: 'Any additional details...', class: 'form-control', :rows => '5' %>
</div>
<%= f.submit 'Request it', :class => 'btn btn-lg btn-danger btn-block' %>
<% end %>
As you can see I've tried calling that #userquery method to display on the view page, but it doesn't show up since it's defined on a different controller. Any recommendations would be awesome.
I would suggest you render results and no results from the same controller/view. A nice clean way to do this is with partials. Your view could look something like:
<% if #articles.blank? %>
<%= render 'no_results' %>
<% else %>
<%= render 'results' %>
<% end %>
Then, you would simply create _no_results.html.erb and populate it with your current new.html.erb contents and do the same for your nominal results page (with partial _results.html.erb).
Related
I'm a total beginner in Rails and I try to use Ransack to filter results.
I have a model called 'adventures' which has many parameters, of which 'main_activity'. I try to implement a form in my homepage, where you can type the kind of activities you are looking for (later I will implement a dropdown so it will be limited to existing activities).
Here is what I have in my pages_controller:
def search
if params[:search].present? && params[:search].strip != ""
session[:bourse_aventuriers_search] = params[:search]
end
arrResult = Array.new
if session[:bourse_aventuriers_search] && session[:bourse_aventuriers_search] != ""
#adventures_main_activity = Adventure.where(active: true).all
else
#adventures_main_activity = Adventure.where(active: true).all
end
#search = #adventures_main_activity.ransack(params[:q])
#adventures = #search.result
#arrAdventures = #adventures.to_a
end
And in my home.html.erb
<%= form_tag search_path, method: :get do %>
<div class="row">
<div class="col-md-6">
<%= text_field_tag :search, params[:search], placeholder: "Quelle activité ?",
class:"form-control" %>
</div>
For the moment, whatever I type in the form, I get all the 'adventures' in the data base ; I find it logical because I did not change the 1st #adventures_main_activity = Adventure.where(active: true).all.
I don't know how to change it so that It will give me only the adventures whose main_activity is the keyword that I type in the form. Can anyone help me ? Thanks :)
I think you have a lot of surplus code in your search. Your controller should only need the #q parameter as follows:
#q = Adventure.ransack(params[:q])
#adventures = #q.result
The #adventures will then return any matches as an active record.
If you pass no parameters then the query will return all records (same as doing an Adventure.all).
When you submit the form the ransack search will pass a "q" param which will contain all the form items. Your's may look something like this:
"utf8"=>"✓", "q"=>{"search_cont"=>"rock climbing"}, "commit"=>"Search", "controller"=>"adventures", "action"=>"index"
If you use a debugger you can see this information by typing "params" in the command line. It will also appear in the server output.
Using an example of one I did in my application here is the exact code I used:
View:
<%= search_form_for #q do |f| %>
<div class="form-group col-sm-6">
<%= f.label :email_cont, "Email:" %>
<%= f.search_field :email_cont, :placeholder => "Please enter and email to search for", :class => "form-control" %>
</div>
<div class="form-group col-sm-3">
<%= f.submit 'Search', :class => 'btn btn-primary' %>
<%= link_to 'Reset', users_path, :class => 'btn btn-default' %>
</div>
<% end %>
Controller
def index
#q = User.ransack(params[:q])
#users = #q.result(distinct: true).order(:email).page params[:page]
end
The classes are just Bootstrap CSS which you won't need if you are not using bootstrap.
EDIT
The search_form_for #q has to exactly that and the #q has to be set in the params for it to work. Ransack is very specific about them. So your #search in
#search = #adventures_main_activity.ransack(params[:q])
should be #q. In your view change your form_tag to search_form_for and it should work. Good luck.
I've been looking for a solution to this for quite sometime now but I cannot wrap my head around on how to solve this. I'm new to Rails/Ruby programming and would appreciate any direction on this problem.
I have a form that takes in values and creates a Task object. Each Task belongs_to a Lead and a Lead has_many Tasks.
The path for a new Task takes in the lead_id as one of the parameters.
/accounts/:account_id/reps/:rep_id/leads/:lead_id/tasks/new
But my goal is to also allow the user to use the form to create a Task for any lead. So, ideally, he should be allowed to select a lead from a dropdown and that lead_id needs to travel through to the CREATE method.
Here's my form:
<%= simple_form_for(#task, url: account_rep_lead_tasks_path) do |f| %>
<%= f.error_notification %>
<div class="field">
<div class="control">
<div class="select">
<%= f.collection_select :lead_id, #leads, :id, :name %>
</div>
</div>
</div>
<div class="field">
<div class="control">
<%= f.input :task_type, required:true, autofocus:true, input_html: {class: "input"}, wrapper: false, label_html: {class: "label"} %>
</div>
</div>
<div class="field">
<div class="control">
<%= f.input :description, required:true, autofocus:true, input_html: {class: "textarea"}, wrapper: false, label_html: {class: "label"} %>
</div>
</div>
<div class="field">
<div class="control">
<%= f.button :submit, class: "button is-primary" %>
</div>
</div>
By default, I render the new Task form for the latest Lead. Suppose the latest Lead created has an ID of 21, here's what shows in the URL:
http://localhost:3000/accounts/1/reps/2/leads/21/tasks/new
When I submit the form however, even though I'm selected a different lead via the collection_select input in the form for lead_id, the Task isn't being created for the selected Lead but being created for lead with id = 21.
The server logs show that the parameters that are being sent to the CREATE method are:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"sKwctK492JH01yXilEI7jSSmv53ggiJuRBH/9Ate2AS+Lx53CO5BqgIOh44uvhFi6MPJ+Og1EY0U8m2BzqC9eA==", "task"=>{"lead_id"=>"16", "task_type"=>"Hello", "description"=>"Is it me you're looking for?"}, "commit"=>"Create Task", "account_id"=>"1", "rep_id"=>"2", "lead_id"=>"21"}
As you can see, there's a lead_id = 16 (which means that the form is taking the input correctly) but also another lead_id = 21 is present for which the Task is being created.
I want the Task to be created for lead_id = 16. Any idea on what I should be doing?
Here's my Task create controller action
def create
#account = current_account
#rep = current_account.reps.find(params[:rep_id])
#lead = #rep.leads.find(params[:lead_id])
#task = #lead.tasks.build(new_task_params)
if #task.save
redirect_to account_rep_lead_task_path(#rep.account_id,#rep.id,#lead.id,#task)
else
render 'new'
end
end
Try below code
def create
#account = current_account
#rep = current_account.reps.find(params[:rep_id])
#lead = #rep.leads.find(params[:task][:lead_id])
#task = #lead.tasks.build(new_task_params)
if #task.save
redirect_to account_rep_lead_task_path(#rep.account_id,#rep.id,#lead.id,#task)
else
render 'new'
end
end
You'll find lead_id under params[:task] hash. Like: params[:task][:lead_id]
You are getting 2 different lead_id because, first, you have url parameter lead_id which is defined in your routes:
/accounts/:account_id/reps/:rep_id/leads/:lead_id/tasks/new
And Second, it is from your form. So if you want to get lead_id from your form, you can use:
params[:task][:lead_id]
else
params[:lead_id] which is defined in your URL Parameter.
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.
I am trying to build a log in system by this tutorial:
http://www.youtube.com/watch?v=h0k6DFIStFY
My form looks like this:
<!DOCTYPE html>
<div id="content">
<%= flash[:alert1] %>
<%= form_for(:sessions, :url => sessions_path , :html => {:id => "login-form"}) do |f| %>
<fieldset>
<p>
<%= label_tag :name ,"Username:" %>
<%= text_field_tag :name, params[:name] , :class => "round full-width-input", :autofocus=>true %>
</p>
<p>
<%= label_tag :password, "Password:" %>
<%= password_field_tag :password, params[:password], :class => "round full-width-input" %>
</p>
<%= submit_tag "Login", :class=> "button round blue image-right ic-right-arrow" %>
</fieldset>
<% if (flash[:status] == FALSE) %>
<br/><div class="information-box round"><%= flash[:alert] %></div>
<% end %>
<% end %>
</div> <!-- end content -->
and my controller looks like this:
class SessionsController < ApplicationController
def login
end
def create
user = User.authenticated?(params[:sessions][:name], params[:sessions][:password])
flash[:alert1] = "dummy"
if user
redirect_to '/login'
else
flash[:status] = FALSE
flash[:alert] = "Invalid username and password"
redirect_to '/login'
end
end
def new
end
end
when trying to submit, i get this error:
undefined method `[]' for nil:NilClass
in the following line:
user = User.authenticated?(params[:session][:name], params[:session][:password])
Did i use incurrectly in the session key ?
Thanks,
Gal!
I think you have some problems in your form: you are using a form_for and then in fields you are using text_field_tag.
I would correct it in something like :
<% form_for sessions .... do |f| %>
<%= f.text_field :name %>
and so forth.
This will generate the params you want in your controller
params[:sessions][:name]
params[:sessions][:password]
I would suggest you to use some gem instead of building an entire system of authentication, which can be quite tricky in terms of security. Have you taken a look at https://github.com/plataformatec/devise?
Hope it helps
It looks like you're using an external authentication gem, perhaps one of these?
https://www.ruby-toolbox.com/categories/rails_authentication
You need to include a require <gem_name> line at the top.
I have this code that allows user to click Add Date to show another line to specify a date time. Screenshot shows user entered two dates:
<fieldset class="date_fieldset">
<%= f.label :user_event_date, "Date", class: "info_inline_control info_label" %>
<%= f.text_field :user_event_date, class: 'datepicker' %>
<div class="user_event_inline_container margin_left_ten padding_right_gone">
<%= f.label :start_time, "Start", class: 'info_inline_control info_label five_margin_right' %>
<%= f.time_select :start_time, {:ampm => true}, class: (field_class(#user_event, :start_time) + 'info_inline_control') %>
</div>
<div class="user_event_inline_container margin_left_ten padding_right_gone">
<%= f.label :end_time, "End", class: 'info_inline_control info_label five_margin_right' %>
<%= f.time_select :end_time, {:ampm => true}, class: (field_class(#user_event, :end_time) + 'info_inline_control') %>
</div>
<%= f.hidden_field :_destroy %>
<%= link_to "delete", '#', class: 'remove_fields margin_left_ten' %>
</fieldset>
<script type="text/javascript">
$(function() {
$('.datepicker').datepicker({
dateFormat: "dd-mm-yy"
});
});
</script>
But if some other, non-related field elsewhere on the form has a validation error, and the errors are reported at the top of the form, then the two lines for the user specified dates are gone, and clicking the Add Date button makes the user start over to specify the dates again. How can I prevent page refresh to show validation errors wiping out user selected dates?
Here are the new, edit, and create controller action methods:
def new
if !signed_in?
redirect_to signin_path
else
#user_event = UserEvent.new
#user_event.event_dates.build
end
end
def edit
end
def create
#user_event = current_user.user_events.build(params[:user_event])
if #user_event.save
flash[:success] = "Event was successfully posted!"
redirect_to root_url
else
render action: :new
end
end
As always, thanks very much for your answers in advance!
This solves it:
<div>
<%= f.fields_for :event_dates do |builder| %>
<%= render 'event_date_fields', f: builder %>
<% end %>
</div>
Before, I had an empty div, and Javascript would add an event date each time the Add Date link was clicked. But when the page is re-rendered, either due to validation errors, or else because used is editing the event, the div needs f.fields_for to render what already exists.
Man I'm loving Rails, and the community, because I get pieces of the puzzle, and figure out the rest.