Display Algolia results on product view - ruby-on-rails

I'm new on Ror,
I would like to display on my products.search page all my products cards avalaible, and add an algolia searchbar filtering and displaying results cards instead of all the products on this page.
I know it's not that hard but I don't succeed to make it works.
My algolia index works correctly since I get all my products on Algolia website.
Actually I don't find the good method to put in my controller and the good code to put in my view...:-(
Thk you for your help.
Here is my code:
app.js:
//= require algolia/v3/algoliasearch.min
ProductsController.rb:
def search
#products = Product.where(active: true)
???????
end
Product.rb:
include AlgoliaSearch
algoliasearch if: :active? do
attribute :name, :brand, :category, :color, :size, :price
end
products/search.html.erb:
<!-- Algolia searchbar -->
<!-- HTML Markup -->
<div class="aa-input-container" id="aa-input-container">
<input type="search" id="aa-search-input" class="aa-input-search" placeholder="Trouver un article..." name="search" autocomplete="off" />
<svg class="aa-input-icon" viewBox="XXXXXXXX">
<path d="XXXXXXXXXX" />
</svg>
</div>
<!-- Include AlgoliaSearch JS Client and autocomplete.js library -->
<script src="https://cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js"></script>
<script src="https://cdn.jsdelivr.net/autocomplete.js/0/autocomplete.min.js"></script>
<!-- Initialize autocomplete menu -->
<script>
var client = algoliasearch('XXXXX', 'XXXXXXXXXX');
var index = client.initIndex('Product');
//initialize autocomplete on search input (ID selector must match)
autocomplete('#aa-search-input',
{ hint: false }, {
source: autocomplete.sources.hits(index, {hitsPerPage: 5}),
//value to be displayed in input control after user's suggestion selection
displayKey: 'name',
//hash of templates used when rendering dataset
templates: {
//'suggestion' templating function used to render a single suggestion
suggestion: function(suggestion) {
return '<span>' +
suggestion._highlightResult.name.value + '</span><span>' +
suggestion._highlightResult.category.value + '</span>';
}
}
});
</script>
<div class="col-xs-12 col-md-9">
<% #products.each do |product| %>
<% if product.active? %>
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="panel panel-default">
<div class="panel-heading preview">
</div>
<div class="panel-body">
<strong><%= link_to product.name, product %></strong>
<strong><%= product.price %> euros</strong>
</div>
</div>
</div>
<% end %>
<% end %>
</div>

To display Algolia on your current view you can just rely on Front-end search, therefore you can remove the #products = Product.where(active: true) line in your controller and the loop in your view.
That said, your code seems correct. Do you have any records in your Algolia index? If not, you can force the reindexing by using Product.reindex!.

Related

How to access a single attribute of associated model inside a loop?

I extremely need your assistance. I have many to many :through relationship models: Product, Category and Categorization(as intermediate model). In my view I want to iterate through #products and fetch category's
field "title" on each iteration.
Here's my view:
<div class="col-md-9">
<div class="row">
<section id="projects">
<ul id="thumbs">
<!-- Item Project and Filter Name -->
<% #products.each do |product| %>
<% product.categories.each do |category| %>
<li class="item-thumbs col-md-4 <%= category.title %> ">
<% end %>
<!-- Fancybox - Gallery Enabled - Title - Full Image -->
<a class="hover-wrap fancybox" data-fancybox-group="gallery" title="The City" >
<span class="overlay-img"></span>
<%= icon 'font-icon-plus' %>
</a>
<!-- Thumb Image and Description -->
<%= image_tag product.product_images, alt: product.description %>
<p><%= product.price %></p>
</li>
<!-- End Item Project -->
<% end %>
</ul>
</section>
</div>
As you see, I need to get category's title on each iteration so as to insert it to li "class" and link each product tab to a menu "li".
The problem is that when I iterate through #categories inside #products loop, it executes just once therefore I don't get category's title for each product.
It looks to me like your loop is repeatedly creating the opening li tag rather than collecting all the category titles like you want, resulting in invalid HTML. Try writing your markup like so instead:
<div class="col-md-9">
<div class="row">
<section id="projects">
<ul id="thumbs">
<!-- Item Project and Filter Name -->
<% #products.each do |product| %>
<!-- RELEVANT CHANGES RIGHT HERE! -->
<li class="item-thumbs col-md-4 <%= product.categories.pluck(:title).join(' ') %>">
<!-- Fancybox - Gallery Enabled - Title - Full Image -->
<a class="hover-wrap fancybox" data-fancybox-group="gallery" title="The City" >
<span class="overlay-img"></span>
<%= icon 'font-icon-plus' %>
</a>
<!-- Thumb Image and Description -->
<%= image_tag product.product_images, alt: product.description %>
<p><%= product.price %></p>
</li>
<!-- End Item Project -->
<% end %>
</ul>
</section>
</div>
</div>
This uses Rails' handy pluck method to grab all the relevant category titles directly from the database, then joins them together with spaces to make a valid class string. Is this the effect you were looking for?

Reading erb form fields, Rails4

Question about Rails4, I trying to retrieve the "Find Stuff" variable, in the erb form. This
is a search field, using zurb foundation - so the extra styling annotations floating around.
I don't have a model as this is just a form for reading the search input field - which is
in the tag, with placeholder as "Find Stuff".
To use normal Rails4 terminology, I would
like to pass the value of the "Find Stuff" field to the salutation controller, and I tried
many ways, but was unsuccessful, when I used render params[:post].inpect, it shows nil -the
variables that I pass to the controller, on clicking on the "Search" link_to, link. I tried adding an id field to the tag, and that too showed nil on render params[:post].inspect.
Any help, thanks in anticipation.
hello.html.erb form below.
<html>
<body>
<nav class="top-bar" data-topbar>
<ul class="title-area">
<li class="name">
<h1>Hello World!</h1>
</li>
<li class="toggle-topbar menu-icon"><span>Menu</span>
</li>
</ul>
<ul class="right">
<li class="has-form">
<div class="row collapse">
<div class="large-8 small-9 columns">
<input type="text" placeholder="Find Stuff" >
</div>
<div class="large-4 small-3 columns">
<%= link_to "", :controller =>
'salutation', :action =>'hello',
:class=>"alert button expand" %>
</div>
</div>
</li>
</ul>
</section>
</nav>
</body>
</html>
Controller follows
Salutation Controller follows
class SalutationController < ApplicationController
def new
#test = ''
end
def hello
#message = 'Hello World!'
#test = params[:Find_Stuff]
end
end
Wrap your search box in a form element, give your input a name and away you go. You can use the rails form helpers as well - see http://guides.rubyonrails.org/form_helpers.html which has a nice intro to creating a search form
<div class="row collapse">
<%= form_tag("/salutation/hello", method: "post") do %>
<div class="large-8 small-9 columns">
<%= text_field_tag(:find_stuff) %>
</div>
<div class="large-4 small-3 columns">
<%= submit_tag("Search") %>
</div>
<% end %>
</div>
Further to #slapthelownote's answer, the reason you're getting an error is because you're not passing any params to your controller
We've got something like what you want working at http://firststopcosmeticshop.co.uk (top search box) -- using a form_tag
If you want to see live code, I'll be happy to post!
Params
Using a form allows you to set various variables & then submit them to the controller as you've set them. I'd recommend using the form in the other answer, but to understand how it works, you need to read up on the Rails forms tutorial
Basically, the params hash is populated in the middleware of Rails -- from any data sent by HTTP to your backend
With links, you can only send GET params (domain.com/route&params=value), whilst with HTML forms, you can set POST params which are passed through the browser (not the URL)

facebook comments plugin to show comments dynamically

i use facebook comments plugin https://developers.facebook.com/docs/plugins/comments/
for every page in my site
and i show the facebook comments by fetching from json request
https://graph.facebook.com/comments/?ids=abc.com/
so when i update comment in facebook plugin, i would like to get the comments in my site to get dynamically updated
my code in controller
#fb_res=HTTParty.get('https://graph.facebook.com/comments/?ids=abc.com/')
fb_json=JSON.parse(#fb_res)
#fb_comment = fb_json["abc.com/"]["comments"]["data"].map {|x| [x["from"]["id"],x["message"],x["from"]["name"]]}
my views :
<% #fb_comment.each do |fb| %>
<li>
<div class="pic_commnt">
<div class="pic">
<div class="pic_image">
<img src="http://graph.facebook.com/<%= fb[0].to_s %>/picture?type=square" alt="" />
</div>
<span class="pic_name"><%= fb[2].to_s %></span>
</div>
<div class="pic_comments">
<p>
"<%= fb[1].to_s %>"
</p>
</div>
</div>
</li>
<% end %>
i would like to get this section updated dynamically

How do I close the container <div> in a loop?

I have a list of products and I want to show an ad in the product feed.
I want something like:
<div id="container">
<div id="product">Bla..</div>
<div id="product">Bla..</div>
<div id="product">Bla..</div>
</div>
<div id="add">
Adsense Stuff
</div>
<div id="container">
<div id="product">Bla..</div>
<div id="product">Bla..</div>
<div id="product">Bla..</div>
<div id="product">Bla..</div>
<div id="product">Bla..</div>
</div>
In ERB, I would have:
<div id="container">
<% productes.each_with_index do |product,index| %>
<div id="product"><%= product %></div>
<% if index == 2 %>
</div>
<div id="add">
Adsense Stuff
</div>
<div id="container">
<% end %>
<% end %>
</div>
How you translate this to Haml or Slim?
I don't want to break the loop in two loops for two reasons: I don't know the products count by page and I have some more elaborate code which uses the same HTML tricks with the Rails cycle() helper. So, it will help me a lot to find a trick to make it possible.
Haml lets you write raw HTML as output when you want it. Although weird, you can use this to achieve your goals here, as you did with Erb:
TEMPLATE = '
.container
- products.each_with_index do |product,index|
- if index == 2
</div>
<div class="ad">AdSense Stuff</div>
<div class="container">
.product<
= product
'
require 'haml'
products = %w[ cat box kitten shoes hounds ]
puts Haml::Engine.new(TEMPLATE).render binding
#=> <div class='container'>
#=> <div class='product'>cat</div>
#=> <div class='product'>box</div>
#=> </div>
#=> <div class="ad">AdSense Stuff</div>
#=> <div class="container">
#=> <div class='product'>kitten</div>
#=> <div class='product'>shoes</div>
#=> <div class='product'>hounds</div>
#=> </div>
The indentation looks weird, but you can see that you have two containers with the AdSense stuff outside either.
In HAML
-products.each_with_index do |product,index|
.product= product
-if index == 2
.ad= Adsense Stuff
I wouldn't bother with the container, just set up the css to deal with the product and ad classes. (Which also brings up the fact that you have multiple ids of the same name, these should be changed to classes).
- products.each_with_index do |product,index|
.product
= product
- if index == 2
.ad= Adsense Stuff
This should do it?
A possible Haml solution, using the surround helper:
.container
-products.each_with_index do |product,index|
.product=product
-if index == 2
=surround "</div>", "<div class='container'>" do
.add
Adsense stuff
This is a bit of a hack, in that we're "faking" closing and opening the container div; as far as Haml knows we're still in it. For this reason it also introduces a bit of repetition in that you have to specify the "container" class (and any other attributes that div might have) in two places.
This solution is similar to #Phrogz's solution but this is a bit more "Haml-ly" and allows you to use Haml syntax to define the add div.

Ruby on Rails jQuery Visual Effect

I am working on a search function on RoR that basically just has a cool visual effect when a user clicks the search button.
Here is the code in my view for search.rhtml
<html>
<head>
<title>Tutor</title>
<%= javascript_include_tag :defaults %>
</head>
<body>
<h1></h1>
<%= form_remote_tag :url =>{ :action => :search_results }, :update => "results" %>
<fieldset>
<legend>Tutor Search.</legend>
<label for="searchItField">Keyword Search.</label>
<input class="tfield" type="text" value="FIND YOUR TUTOR HERE" name="searchItField" id="searchItField" />
<span id="Submit_search">
<span id="Submit_search_hover"><input type="submit" id="Submit" value="Search" /></span>
</span>
</fieldset>
</form>
<div id="results">
</div>
</body>
</html>
Here is the search_results.rhtml which is what gets displayed in the results div in search.rhtml
<% for tutors in #tutors %>
<%= tutors.first_name %> <br/>
<% end %>
And finally here is my controller and actions.
class TutorsController < ApplicationController
def search
end
def search_results
#tutors = Tutors.find_by_sql('SELECT * FROM tutors')
end
end
What I want to do is basically create an effect that when the search results are loaded because of the ajax call that it would slide up. I am using jrails. Exactly how this site does it. http://keyonary.com/#/paste
In short, to get you started, you will need to do the following:
use observe_field on the input-field, which retrieves data from a controller-method and will update a certain div with the results
create a corresponding controller-method that will retrieve the items (use your search_results)
create a view for that controller-method that will show the data with the required effects and animation.

Resources