Duplicate Results From Search Params - ruby-on-rails

I have a search method and two models, restaurants and menus.In the menu search method, if I search for "chicken" it shows the closest restaurants near the location that sells meals with word chicken example "chicken sandwich" with the use of association. The problem is, if a restaurant sells multiple chicken meals the restaurant is rendered several times.I want to be able to show restaurants once and when the button is clicked a modal shows the meals with "chicken" in the name using a loop if there are multiple meals with chicken. I tried adding uniq & uniq(&:restaurant_id) in the ActiveRecord and also controller & also trying "DISTINCT" using sql but nothing.
Controller
def search_for_menus
##restaurant= Menu.restaurant.all
#menus = Menu.search_for_menus(params)
end
Menus Model
belongs_to :restaurant
reverse_geocoded_by "restaurants.latitude", "restaurants.longitude"
def self.search_for_menus(params)
menus=Menu.where("dish LIKE ?", "%#{params[:dish]}%") if params[:dish].present?
menus = menus.where("menus.price <=?",params[:max ])
menus = menus.where("menus.price >=?",params[:min ])
menus= menus.joins(:restaurant).near(params[:location],2)
menus
end
end
Search Page HTML
<% if #menus.present? %>
<%#menus.each do |menu| %>
<br>
<br>
<div id ="restaurants">
<div class="box">
<div class="thumbnail box-image">
<%= link_to (image_tag (menu.restaurant.thumbnail.url(:medium))),restaurant_path(menu.restaurant),'data-no-turbolink' => true%>
<div class="caption">
<h3 class="text-center"><%=menu.restaurant.name%></h3>
<p class="text-center">View Food</p>
</div>
</div>
</div>
<div id="modal-<%= menu.id %>" class="modal fade bs-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="col-md-6">
<p><%= menu.dish %></p>
</div>
<div class="col-md-6">
<p><%= menu.price %></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
</div>
<%end%>
</div>
<%else%>
<p>no posts</p>
<%end%>

What you need to start with, I think, is the restaurants for which there exists a matching menu item.
restaurants = Restaurant.near(params[:location],2).
where(Menu.where("menus.restaurant_id = restaurants.id").
where("dish LIKE ?", "%#{params[:dish]}%").
where("menus.price <=?",params[:max ]).
where("menus.price >=?",params[:min ]).exists)
This is guaranteed to return one row per restaurant.
You might want ILIKE for a case insensitive dish search, if your RDBMS supports it.
You can then list the appropriate menu items for the matching restaurants.

After discussing over chat, here's an update, thanks #David for the query.
Menu model:
belongs_to :restaurant
reverse_geocoded_by "restaurants.latitude", "restaurants.longitude"
def self.search_for_restaurants(params)
Restaurant.near(params[:location],2).
where(Menu.where("dish LIKE ?", "%#{params[:dish]}%").
where("menus.price <=?",params[:max ])
where("menus.price >=?",params[:min ]).exists)
end
Put this in the restaurant model (here you are going to fetch all the matching menus for the view):
def search_for_matching_menus dish
menus.where("dish LIKE ?", "%#{dish}%")
end
View (you have to adjust it to your needs, I just want you to understand the idea):
<% if #restaurants.present? %>
<%#restaurants.each do |restaurant| %>
<br></br>
<br></br>
<div id ="restaurants">
<div class="box">
<div class="thumbnail box-image">
<%= link_to (image_tag (restaurant.thumbnail.url(:medium))),restaurant_path(restaurant),'data-no-turbolink' => true%>
<div class="caption">
<h3 class="text-center"><%=restaurant.name%></h3>
<%= restaurant.search_for_matching_menus(#dish).each do |menu| %>
<%= menu.id %>
<% end %>
</div>
</div>
</div>
<%end%>
<%end%>
And finally this has to go on the controller that calls the search, to forward the dish parameter:
#dish = params[:dish]

Related

Trying to collect a list of ids from checkboxes to delete from my database

I'm creating an app (personal project) that'll help us schedule and record Nerf tournaments for a group I hang out with. I have tournament and player models. A tournament can have multiple players.
I want to be able to check multiple players and choose to delete them from the tournament. The thing is though is that all of my players are rendered in a nested partial. And my tournament partial has a form already inside of it.
Here is _tournament.html.erb:
<section class="panel" id="<%= dom_id(tournament) %>">
<h1 class="heading">
<%= tournament.name %>
</h1>
<ul>
<%= render tournament.players %>
</ul>
<section class="add_players">
<%= form_for [tournament, Player.new] do |f| %>
<div class="form-group">
<%= f.text_field :name %>
</div>
<div class="form-group">
<%= f.text_field :team %>
</div>
<%= f.submit "Add Player", class="button blue" %>
<% end %>
</section>
<section class="delete_all">
<button class="button red" type="button">Delete Players</button>
</section>
</section>
and here is _player.html.erb:
<li id="<%= dom_id(player) %>">
<div class="player">
<%= check_box_tag "player_ids[]", player.id %>
<span class="name"><%= player.name %></span> |
<span class="team"><%= player.team %></span>
</div>
</li>
I'm familiar with Railscast #52 where he does a simpler example of this, but I can't figure out how to get all of those checked checkboxes in the tournament partial and use those ID's to delete those players from the tournament.
I've tried wrapping the _tournament.html.erb partial inside of a form_tag but it breaks some styling (and HTML doesn't really allow that as a standard.)
Any guidance or help would be great!
What you are doing is creating a form that posts to /tournaments/:tournament_id/players which makes sense if you are assigning the players one by one or creating a single player.
It does not make sense at all if you are assigning multiple players to a tournament. Because you are actually changing the parent resource.
In that case you should be sending a POST request to /tournaments (to create a tournament) or a PATCH request to /tournaments/:id (to modify an existing record).
<%= form_for tournament do |f| %>
<div class="form-group">
<%= f.label :player_ids, "Assign players" %>
<%= f.collection_check_boxes :player_ids, Player.all, :id, :name %>
</div>
<%= f.submit %>
<% end %>
class TournamentsController < ApplicationController
# ...
private
def tournament_params
params.require(:tournament)
.permit(:foo, :bar, player_ids: [])
end
end
If you want to be able to create multiple player records in a single request you should use nested attributes and fields_for.
To unassign all the players you can do a PATCH request to /tournaments/:id
with an empty array as the value for tournaments[:players_ids]. You can do this with javascript by creating a handler that unchecks all the checkboxes and submits the form when the user clicks the button (or confirms it).
Or you could create a custom DELETE /tournaments/:tournament_id/players route.
resources :tournaments do
resources :players
delete :players, on: :collection, action: :delete_all_players
end

bootstrap format rails output in columns

I'm trying to figure out how to align my rails output into 3 columns of equal length using bootstrap. Basically i need three columns, the issue is that if I have 12 "skills" i would like them to be divided up into 4 skills in each section, etc...
But I can't figure out how to output the data in anything but a one column list. I'm thinking I need something like this?
<div class="col-md-4">
< ... output of skills >
</div>
<div class="col-md-4">
< ... output of skills >
</div>
<div class="col-md-4">
< ... output of skills >
</div>
This is my current output that makes a list, I would like to somehow make 3 columns out of the output.
<div class="col-md-12">
<table>
<!-- one-to-many association to loop through a users skills -->
<% #user.skills.each do |skill| %>
<tr>
<td>
<br />
<h4><b><%= link_to skill.name, edit_user_skill_path(user_id: #user.id, id: skill.id) %></b></h4>
</td>
</tr>
<% end %>
</table>
</div>
update
here's the solution I implemented based off of martin's suggestion.
<% #user.skills.in_groups_of(3, false).each do |group| %>
<div class='row'>
<% group.each do |skill| %>
<div class='col-md-4'>
<div><%= skill.name %></div><br />
</div>
<% end %>
</div>
<% end %>
also because the text was being displayed within a panel i found that it was running off the edge so had to use this for the CSS
.panel-body{
word-wrap: break-word;
}
You can try using in_groups_of method: https://apidock.com/rails/v4.2.7/Array/in_groups_of

Show only names that belong to a code

So in my app a guest searches for their RSVP code in the code/index.html page then clicks on a continue link that brings them to the rsvp page. I am trying to show only names that belong to the specific code on the RSVP but currently all names are showing up. I have passed the code as a param in the link on the index page but when I get to the rsvp page it is showing up in the url with a period which doesn't seem right ex: /rsvp.1
so I am guessing that this is where I am going wrong but I cant figure out why:
associations
Guest belongs_to :code
Code has_many :guest
code/index.html.erb
(page with the link that takes user to rsvp page and passes the params to rsvp page)
<h2><%= link_to 'Continue', rsvp_path(code) %></h2>
code_controller
def index
#codes = Code.search(params[:search])
end
def rsvp
code_id = params[:code]
#guests = Guest.where("code_id", "#{code_id}")
end
code/rsvp.html.erb
<div class="row">
<div class="box">
<div class="col-lg-12">
<form class="row form-inline">
<% #guests.each do |guest| %>
<%= guest.name %>
<% end %>
<div class="form-group">
<p> Will you be attending the wedding of Kristen Albrecht and Chris Alford September 1, 2017? </p>
<button aria-haspopup="true" class="btn btn-default dropdown-toggle" ngbdropdowntoggle="" type="button" aria-expanded="false">
Yes</button>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">No</button>
</div>
</form>
</div>
</div>
</div>
routes
resources :codes
resources :guests
get '/code' =>'codes#code'
get '/rsvp' =>'codes#rsvp'
To make sure that code is a parameter in the URL, you have to make the following changes:
routes.rb
get '/rsvp/:code' =>'codes#rsvp'
code/index.html.erb
<h2><%= link_to 'Continue', rsvp_path(code: code) %></h2>
This way params[:code] will have a value in the code_controller
Okay I figured it out:
I changed the link on the index page to
<%= link_to "Continue", {:controller => "codes", :action => "rsvp", :code_id => code.id }%>
then I changed the controller code to
def rsvp
#guests = Guest.where(code_id: params[:code_id])
end

Ruby on rails Merge two routes

So i have the controller named collection and the model name products.
The collection page is showing all the products.
Here is the code that show's the products
<% #products.each do |x| %>
<div class="col-lg-3">
<div class="product-container animated fadeIn">
<div class="product-image-holder">
<%= image_tag x.image1.url(:fhd) %>
</div>
<div class="product-title-holder">
<span class="product-title"><%= x.title %></span>
</div>
</div>
</div>
<% end %>
Now i want to wrap each product in it's own link ( link to single product )
i managed to do that but the link will be www.localhost.com/product/1 instead of this i want to be www.localhost.com/collection/product/1
Any help ? :)
This are the routes
get 'collection', to:'collection#index'
resources :product
Use a scope
scope '/collection' do
resources :products
end
More info here: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing

dynamic bootstrap tabs with rails

I am trying to get rails to generate dynamic navigation tabs that refer to groups user is enrolled at. Basically, what I want to achieve is to dynamically have tabs named after groups that user is enrolled at (which is working fine) and then showing the content of each group by clicking on its tab (which is not working properly for some reason). The page loads data correctly but toggling between tabs doesn't work
Here is the code in the view
<div class="tabbable tabs-left">
<div class="row">
<div class="col-md-4">
<ul class="nav nav-pills nav-stacked">
<% current_user.group.each do |group| %>
<li><a href="#<%= group.name %>" data-toggle="tab">
<%=group.name %></a></li>
<% end %>
</ul>
</div>
<div class="col-md-8">
<div class="tab-content">
<% current_user.group.each do |group| %>
<div class="tab-pane fade <%= 'in active' if current_user.group.first == group %>" id="<%=group.name%>">
<% if current_user.group_feed(group.id).any? %>
<ol class="microposts">
<%= render current_user.group_feed(group.id) %>
<%= group.name %>
</ol>
<% end %>
</div>
<% end %>
</div>
</div>
</div>
</div>
Is there something that I am missing?
The problem is group.name producing an invalid html id attribute.
html ids should not start with a number(numbers anywhere else are ok), and have no spaces. Example:
Invalid:
1foo
aaa b
Valid:
foo1
aaa-b
group.name.parameterize will remove any odd chars(#£$ etc) and replace spaces with "-" so use that.
You also want to make this unique as things with names like: "foo" and "foo!" will parameterize to the same thing: "foo".
I'd go with:
id="<%=(group.name.gsub(/[0-9]+/, "")+group.id.to_s).parameterize%>"
This code, removes any number from the name(it only really applies at the start of the id) then adds the id on the end making it unique.

Resources