Rails Searching in database - ruby-on-rails

I want a searchfunction that can search strings in Database.
What I tried is:
def search_user
#users_search = User.where("lastname LIKE ?", "#{#search}%")
redirect_to :back
end
For example if I type H it should show all Users with a beginning H
View:
<% if #users_search.present? %>
sdf
<% for user in #users_search %>
<%= user.lastname %>
<% end %>
<% end %>

Related

sort by model attribute in controller in user show

I have a book review/discussion site and would like to order all the users books on their profile page based on wether they are currently reading that book. I added a column to the book model called current and when users add a book they can check a box that says "I'm currently reading this." If the user clicks the box then the book object has a :current attribute with a value of "1". If they don't click the box then the value of :current is "0".
In my view I have this code to tell the user which books they are currently reading, and it works fine.
<% if book.current == "1" %>
<h4>I am currently reading this book</h4>
<% end %>
However in my show user controller I can't make it order the incomiing objects by the :current status.
Here's what I've tried:
def show
#user = User.find_by_id(params[:id])
#books= Book.all.sort { |p1, p2| p1.current <=> p2.current }
end
and
def show
#user = User.find_by_id(params[:id])
#books = Book.all
#books = #books.order(:current)
end
and
def show
#user = User.find_by_id(params[:id])
#books = Book.all
#books = #books.order(current: :desc)
end
and, just to make sure it was going the right way
def show
#user = User.find_by_id(params[:id])
#books = Book.all
#books = #books.order(current: :asc)
end
None work. And, none throw errors, they just don't sort it. The "current" book that is last instead of first. Here's the code that displays and loops out the users books. This code also works fine.
<% #user.books.each do |book| %>
<% if params[:id].to_s == book.user_id.to_s %>
<ul class="profileDisplay" >
<img alt="Book Jacket" class="homepageImages" src=<%= book.image %> >
<% if book.current == "1" %>
<h4>I am currently reading this book</h4>
<% end %>
<p><b>Contributor: </b><%= book.user.name %></p>
<p><b>Title: </b><%= book.title %></p>
<p><b>Author: </b><%= book.author %></p>
<p><b>Genre: </b><%= book.genre %></p>
<p><b>Publication Date: </b><%= book.publication_date %></p>
<p><b>Publisher: </b><%= book.publisher %></p>
<p><b>Synopsis: </b><%= book.synopsis %></p>
<% if params[:id] == session[:user_id].to_s || params[:action] == "profile" %>
<%= button_to "Edit Book", book_edit_path(book.id), method: "get", class: "btn btn-primary col-xs-2" %>
<%= button_to "Delete Book", delete_book_path(book.id), method: :delete, data: {confirm: "Are you sure you want to delete this book and all it's reviews?"}, class: "btn btn-danger col-xs-2" %>
<% end %>
</ul>
<% end %>
<% end %>
On view, #user.books are not sorted yet.
You sorted them and assigned it into #books
I think it should be like this
CONTROLLER
def show
#user = User.find_by_id(params[:id])
#books = #user.books.order(current: :desc)
end
VIEW
<% #books.each do |book| %>
<!-- show book records here -->
<% end %>
add default scope in book model
default_scope { order(:current=> :desc) }
and your controller
#user = User.find_by_id(params[:id])
and views
<% #user.books.each do |book| %>
#do whatever
<% end %>

Devise List User Documents

I'm trying to make a 'My Files' Page where the documents that users have uploaded are listed, but am having trouble filtering the documents per user.
Right now it is showing all documents uploaded, instead of the document associated with the user who uploaded it.
I use devise for users
I've tried to change the if statement to various different conditions but cannot seem to filter the documents associated with each user.
This is my code for the 'My Files' page:
<% #documents.each do |document| %>
<% if #document = current_user.documents.find_by(params[:user_id]) %>
<%= link_to document.title, document %>: <%= link_to "Download", document.pdf(:original, false) %>
<% end %>
<% end %>
This is my documents controller code for the myfiles page:
def myfiles
#documents = Document.all
end
Is there a simple way I can filter the documents that are associated with each user?
This method will show documents associated with current user only.
Controller file:
def myfiles
if current_user
#documents = current_user.documents
else
#documents = Document.all
end
end
View file:
<% #documents.each do |document| %>
<%= link_to document.title, document %>: <%= link_to "Download", document.pdf(:original, false) %>
<% end %>
Rails find_by returns the first record found. You're probably looking for where.
In the controller:
#documents = if params[:user_id]
current_user.documents.where(user_id: params[:user_id])
else
Document.all
end
In the view:
<% #documents.each do |document| %>
<%= link_to document.title, document %>: <%= link_to "Download", document.pdf(:original, false) %>
<% end %>
http://apidock.com/rails/ActiveRecord/FinderMethods/find_by
http://apidock.com/rails/ActiveRecord/QueryMethods/where

Using search function in rails to retrieve a result and display it first in the index page

I am trying to implement search functionality in my rails app where I search and display a particular search result first on my index.html.erb view. At the moment I have a search function working and it returns the particular item on its own on the index page.
Ideally I would like to have this item displayed first and then all the other items to display below.
My code is as follows:
brand.rb
def self.search(query)
where("author like ?", "%#{query}%")
end
brand_controller.rb
def index
if params[:search]
#brand = Brand.search(params[:search]).order("created_at DESC")
else
#brand = Brand.all.order(':date')
end
end
I know the where method returns the value as an array so I could probably use array.first to output this result first but is there an easier way to output my desired view. Thanks!
So turned out to be a pretty simple solution, I blame mondays.
All I had to do was create another variable for my search and iterate that result first, then iterate through the rest of the items.
in my controller
def index
#brand = Brand.order('created_at DESC')
if params[:search]
#brand = Brand.search(params[:search]).order("author DESC")
#other = Brand.search_all(params[:search]).order("author DESC")
else
#brand = Brand.all.order('author DESC')
end
end
In my model
def self.search(query)
where("author like ?", "%#{query}%")
end
def self.search_all(query)
where("author not like ?", "%#{query}%")
end
and finally in my view
<% if #brand.any? %>
<% #brand.in_groups_of(2) do |group| %>
<% group.each do |brand| %>
<% if brand %>
<h4> <%= brand.author %></h4>
<a href="<%=brand_path(brand)%>">
<%=image_tag brand.brand_logo, class: 'img-rounded', :"data-uid" => brand.uid %> </a>
<% end %>
<% end %>
<% end %>
<% end %>
<% if #other %>
<% #other.in_groups_of(2) do |group| %>
<% group.each do |other| %>
<% if other %>
<h4> <%= other.author%></h4>
<a href="<%=brand_path(other)%>">
<%=image_tag other.brand_logo %> </a>
<% end %>
<% end %>
<% end %>
<% end %>

Creating multiple objects in a form Rails

So I have an interesting problem I'm working on. I am trying to create multiple objects of the same model in one view. I would like to display all the possible objects in my view, check boxes to select which ones to create, then submit and create all the corresponding objects.
Now the objects to select are gotten using an API request and returned in JSON format. The JSON is then displayed on the view for the user to select, then an array containing all the selected objects is sent back to the controller for creation.
Here is the relevant code that I've tried so far.
objects_controller.rb
def new
#possible_objects = <api call to get objs>
#objects = []
end
def create
params[:objects].each do |obj|
# create and save obj
end
end
objects/new.html.erb
<% form_for #objects do |f| %>
<% #possible_objects.each do |api_obj| %>
<%= check_box_tag(api_obj["name"])%>
<%= api_obj["name"] %>
<% end %>
<%= f.submit %>
<% end %>
This is definitely not the right approach, as the form will not accept an empty array as a parameter. I'm not sure where else to go with this, any pointers in the right direction would be great. Thanks.
Thanks to MrYoshiji for pointing me in the right direction, this is what ended up working
objects_controller.rb
def
#possible_objects = <api call to get objs>
end
def create
params[:objects].each do |object|
new_obj = Object_Model.new( <params> )
new_obj.save
if !new_obj.save
redirect_to <path>, alert: new_obj.errors.full_messages and return
end
end
redirect_to <path>, notice: 'Successfully created.'
end
objects/new.html.erb
<%= form_tag objects_path(method: :post) do %>
<% #possible_objects.each do |api_obj| %>
<%= check_box_tag 'objects[]', api_obj %>
<%= possible_object["name"] %>
<% end %>
<%= submit_tag 'Create'%>
<% end %>
Can you try the following?
# view
<% form_tag my_objects_path(method: :post) do |f| %>
<% #possible_objects.each do |api_obj| %>
<%= check_box_tag 'objects[names][]', api_obj["name"] %>
<%= api_obj["name"] %>
<% end %>
<%= f.submit %>
<% end %>
# controller
def create
params[:objects][:names].each do |obj_name|
YourModelForObject.create(name: obj_name)
end
end
See this comment on the documentation of check_box_tag: http://apidock.com/rails/ActionView/Helpers/FormTagHelper/check_box_tag#64-Pass-id-collections-with-check-box-tags

Why does my search show all results with searching?

I setup a search on my Products index page with PgSearch and Will-Paginate like this:
ProductsController
def index
#products = Product.text_search(params[:query]).page(params[:page]).per_page(5)
end
Products Model
include PgSearch
pg_search_scope :search,
def self.text_search(query)
if query.present?
search(query)
else
scoped
end
end
Product index page
<%= form_tag products_path, method: :get do %>
<%= text_field_tag :query, params[:query] %>
<%= submit_tag "Search", name: nil %>
<% end %>
<% if #products.blank? %>
No Results
<% else %>
<% #products.each do |product| %>
<%= product.name %>
<% end %>
<% end %>
But the problem I'm having now is that when I go to the Product index page, it shows all of the products when I want it to show nothing until a search is done. If the search is blank, return No Results but when you first hit the page it should show nothing. How would this be done?
You probably want to only run a text_search when a search parameter is present. You can put this logic into the view, the controller, or in the model.
In the view
<% if params[:query].present? %>
<% if #products.blank? %>
No Results
<% else %>
<% #products.each do |product| %>
<%= product.name %>
<% end %>
<% end %>
<% end %>
In the controller
def index
if params[:query].present?
#products = Product.text_search(params[:query]).page(params[:page]).per_page(5)
else
#products = Product.none # NOTE: Rails 4 only
end
end
In the model
# create a new method to encapsulate this search logic then use it in the controller
def self.search(value)
if value.present?
Product.text_search(value)
else
Product.none # NOTE: Rails 4 only
end
end
The old saying goes "fat model, skinny controller" so you might want to opt for the model method which will keep your controller and views simpler.
Put your display logic inside an if statement:
<% if params[:query].present? %>
<% if #products.blank? %>
No Results
<% else %>
<% #products.each do |product| %>
<%= product.name %>
<% end %>
<% end %>
<% end %>
Although I'm not familiar with how pg search works, you could do something like this in your method.
It's a nice refactoring as well as it avoids checking for existence and making decisions on params (code smell)
def self.text_search(query = "")
search(query)
end
As I said, not sure how pg_search works. Maybe when you browse for nothing, it returns all records. If that's the case, you can just have it return an empty array. Something like this would do
def self.text_search(query)
return [] if query.nil?
search(query)
end

Resources