sunspot_solr facet not working in Ruby on Rails - ruby-on-rails

I have a simple application which made with Rails 5 and I'm using sunspot solr for facet searching, everything is OK but facet not working my code is below:
model.rb
searchable do
text :full_name, :interested_topics,:interested_job, :city, :email, :username, :publish_month
text :city
time :created_at
string :publish_month
string :interested_job
end
def publish_month
created_at.strftime("%B %Y")
end
def full_name
first_name + ' ' + last_name
end
controller.rb
#search = User.search do |searcher|
fields = [:full_name, :interested_topics, :interested_job, :city, :email, :username, :publish_month]
cities = [:city]
searcher.any do
fulltext params[:search], :fields => fields
fulltext params[:city], :fields => cities
end
searcher.with(:created_at).less_than(Time.zone.now)
searcher.with(:publish_month, params[:month]) if params[:month].present?
searcher.with(:interested_job, params[:position]) if params[:position].present?
searcher.paginate(:page => params[:page], :per_page => 15)
end
#users = #search.results
index.html.erb
<div id="facets">
<%= render partial: "filter" %>
</div>
index.js.erb
$('#facets').html('<%= escape_javascript(render("filter")) %>');
_filter.html.erb
<h4>Browse by Publish</h4>
<ul class="list-group">
<% for row in #search.facet(:publish_month).rows -%>
<li class="list-group-item">
<input type="checkbox" class="facet-check-box-month" name="month" value="<%= row.value %>" <%= params[:month] == row.value ? "checked" : "" %>>
<%= row.value %>
(<%= row.count %>)
</li>
<% end -%>
</ul>
<h4>Browse by Interest</h4>
<ul class="list-group">
<% for row in #search.facet(:interested_job).rows -%>
<li class="list-group-item">
<input type="checkbox" class="facet-check-box-position" name="position" value="<%= row.value %>" <%= params[:position] == row.value ? "checked" : "" %>>
<%= row.value %>
(<%= row.count %>)
</li>
<% end -%>
</ul>
Checkbox showing well for facet but when I clicking than not querying.
What I'm doing wrong?
Thanks in advance.

You have missed facet calling like on the controller you can add that two lines into User block above the last line like searcher.paginate(:page => params[:page], :per_page => 15)
searcher.facet(:publish_month)
searcher.facet(:interested_job)
Then restart your sunspot:solr server, I think it will work.
For more nicer, on the filter partial use unless #search.nil? for when not found any results than not will show the checkbox like after modified
<% unless #search.nil? %>
<h4>Browse by Publish</h4>
<ul class="list-group">
<% for row in #search.facet(:publish_month).rows -%>
<li class="list-group-item">
<input type="checkbox" class="facet-check-box-month" name="month" value="<%= row.value %>" <%= params[:month] == row.value ? "checked" : "" %>>
<%= row.value %>
(<%= row.count %>)
</li>
<% end -%>
</ul>
<h4>Browse by Interest</h4>
<ul class="list-group">
<% for row in #search.facet(:interested_job).rows -%>
<li class="list-group-item">
<input type="checkbox" class="facet-check-box-position" name="position" value="<%= row.value %>" <%= params[:position] == row.value ? "checked" : "" %>>
<%= row.value %>
(<%= row.count %>)
</li>
<% end -%>
</ul>
<% end %>
Hope it helps

Related

Ruby on Rails SOLR facets between 2 models

In my classifieds app , my "main" model is Classifieds but i have also implemented categorization so Categories has_many :classifieds
Also i have implemented my Categories with awesome_nested_set
And i have Solr search too!
In my sites Classifieds - index.html.erb i render the Classifieds and if search is used i render the corresponding Classifieds.
Now i have implemented a navbar which uses the Category model for navigation.
The navbar shows the Category.roots and the descendants of each root with a dropdown. This leads to the Category - show.html.erb ,where Classifieds are shown according to the Category they are in!
So the question is here:
In my Classifieds - index.html.erb i have successfully implemented Solr facets , which are used as filters but this only works when the user either Searches or just filters in the initial index! So in simple words when he interacts with the Classifieds Controller.
How can i preserve the facet functionality when the user uses the navbar , which means he then interacts with the Category controller
Models:
class Classified < ApplicationRecord
belongs_to :user
belongs_to :category
has_many :photos, dependent: :destroy, inverse_of: :classified
has_many :favorite_classifieds, dependent: :destroy
has_many :favorited_by , through: :favorite_classifieds , source: :user #for the favorite_by to work :source is needed
accepts_nested_attributes_for :photos
searchable do
text :title, :boost => 5
text :model , :created_month , :make , :make_country , :condition ,:treecat,:cat,:price #TO BE CHANGED TO CURRENCY FORMAT
time :created_at
string :treecat
string :price #TO BE CHANGED TO CURRENCY FORMAT
string :created_month
string :cat
string :make_country
string :condition
string :make
string :model
end
def cat
category.root.name
end
def treecat
category.name unless category.name == category.root.name
end
def created_month
created_at.strftime("%B")
end
end
class Category < ApplicationRecord
acts_as_nested_set
has_many :classifieds
end
Classifieds controller index action
def index
#search = Classified.search do
paginate(:page => params[:page] || 1, :per_page => 10)
order_by(:created_at , :desc)
fulltext params[:search]
with(:created_at)
active_model = with(:model ,params[:model]) if params[:model].present?
active_make = with(:make , params[:make]) if params[:make].present?
active_make_country = with(:make_country , params[:make_country]) if params[:make_country].present?
active_condition = with(:condition,params[:condition]) if params[:condition].present?
active_category = with(:cat,params[:cat]) if params[:cat].present?
active_subcategory = with(:treecat,params[:treecat]) if params[:treecat].present?
facet(:model)
facet(:make)
facet(:make_country)
facet(:condition)
facet(:cat , exclude: active_subcategory)
facet(:treecat)
end
#classifieds = #search.results
end
Categories controller show action
def show
#category = Category.find_by_id(params[:id])
end
Classifieds - index.html.erb
<div class="indexbox">
<div class="col-md-2 col-md-offset-1 visible-lg">
<div class="facets">
<h6>Μάρκα</h6>
<ul class="facetlist">
<% for row in #search.facet(:make).rows %>
<li>
<% if params[:make].blank? %>
<%= link_to(row.value, params.merge(:page => 1,:make => row.value).permit!) %> <small class="rowcount"><%= row.count %></small>
<% else %>
<strong><%= row.value %></strong> (<%= link_to "remove", :make => nil %>)
<% end %>
</li>
<% end %>
</ul>
<h6>Χώρα Κατασκευής</h6>
<ul class="facetlist">
<% for row in #search.facet(:make_country).rows %>
<li>
<% if params[:make_country].blank? %>
<%= link_to(row.value, params.merge(:page => 1,:make_country => row.value).permit!) %> <small class="rowcount"><%= row.count %></small>
<% else %>
<strong><%= row.value %></strong> (<%= link_to "remove", :make_country => nil %>)
<% end %>
</li>
<% end %>
</ul>
<h6>Κατάσταση</h6>
<ul class="facetlist">
<% for row in #search.facet(:condition).rows %>
<li>
<% if params[:condition].blank? %>
<%= link_to(row.value, params.merge(:page => 1,:condition => row.value).permit!) %> <small class="rowcount"><%= row.count %></small>
<% else %>
<strong><%= row.value %></strong> (<%= link_to "remove", :condition => nil %>)
<% end %>
</li>
<% end %>
</ul>
<h6>Κατηγορία</h6>
<ul class="facetlist">
<% for row in #search.facet(:cat).rows %>
<li>
<% if params[:cat].blank? %>
<%= link_to(row.value, params.merge(:page => 1,:cat => row.value).permit!) %> <small class="rowcount"><%= row.count %></small>
<% else %>
<strong><%= row.value %></strong> (<%= link_to "remove", :cat => nil %>)
<% end %>
</li>
<% end %>
</ul>
<h6>Κατηγορία</h6>
<ul class="facetlist">
<% for row in #search.facet(:treecat).rows %>
<li>
<% if params[:treecat].blank? %>
<%= link_to(row.value, params.merge(:page => 1,:treecat => row.value).permit!) %> <small class="rowcount"><%= row.count %></small>
<% else %>
<strong><%= row.value %></strong> (<%= link_to "remove", :treecat => nil %>)
<% end %>
</li>
<% end %>
</ul>
</div>
</div>
<% #classifieds.each do |f| %>
<% if !f.sold %>
<div class="center-div" id="index">
<div class="col-lg-12">
<div class="pull-right">
<div class="listingoptions">
<div class="col-md-3">
<p><%= link_to "", new_classified_message_path(:recipient_id => f.user_id , :classified_id => f.id), :class => "glyphicon glyphicon-envelope" , :style => "color:#EFCE7B" %></p>
<%if current_user.favorite_classifieds.collect(&:classified_id).include?(f.id) %>
<p><%= link_to "", favorite_classified_path(f, type: "unfavorite") , :class => "glyphicon glyphicon-heart" , :style => "color:#FF0000", method: :put %></p>
<%else%>
<p><%= link_to "", favorite_classified_path(f, type: "favorite") , :class => "glyphicon glyphicon-heart-empty" , :style => "color:#000000", method: :put %></p>
<%end%>
<p><%= link_to "", editlisting_path(f) , :class => "glyphicon glyphicon-flag" , :style => "color:#EB573B" %></p>
</div>
</div>
</div>
<%= link_to classified_path(f) , :class => "link" do %>
<div class="media">
<div class="mediabox">
<div class="media-left" href="#">
<!-- <img class="media-object" src="..." alt="Generic placeholder image">-->
<% if f.photos.first %>
<%= image_tag f.photos.first.image.url , :class => "media-object"%>
<%end%>
</div>
<div class="media-body">
<h5 class="media-heading"> <%= f.title %></h5>
<small><%= f.created_month %></small>
<% if f.category.parent_id? %>
<small><%= f.category.root.name %></small>
<%end%>
<small><%= f.category.name %></small>
<div class="price ">
<h5><%= f.price %> </h5>
</div>
</div>
</div>
</div>
</div>
</div>
<%end%>
<%end%>
<%end%>
<div class="center-div">
<div class="digg_pagination">
<%= will_paginate #classifieds , :previous_label => '<', :next_label => '>' %>
</div>
</div>
</div>
Categories show.html.erb
<div class="indexbox">
<div class="center-div" id="index">
<div class="categorytitle">
<h4>
<%= #category.root.name %>
<% unless #category.name == #category.root.name %>
<span> >> </span><%= #category.name %>
</h4>
<%end%>
</div>
</div>
<% #category.self_and_descendants.each do |desc| %>
<% desc.classifieds.each do |f|%>
<% if !f.sold %>
<div class="center-div" id="index">
<div class="col-lg-12">
<div class="pull-right">
<div class="listingoptions">
<div class="col-md-3">
<p><%= link_to "", new_classified_message_path(:recipient_id => f.user_id , :classified_id => f.id), :class => "glyphicon glyphicon-envelope" , :style => "color:#EFCE7B" %></p>
<%if current_user.favorite_classifieds.collect(&:classified_id).include?(f.id) %>
<p><%= link_to "", favorite_classified_path(f, type: "unfavorite") , :class => "glyphicon glyphicon-heart" , :style => "color:#FF0000", method: :put %></p>
<%else%>
<p><%= link_to "", favorite_classified_path(f, type: "favorite") , :class => "glyphicon glyphicon-heart-empty" , :style => "color:#000000", method: :put %></p>
<%end%>
<p><%= link_to "", editlisting_path(f) , :class => "glyphicon glyphicon-flag" , :style => "color:#EB573B" %></p>
</div>
</div>
</div>
<%= link_to classified_path(f) , :class => "link" do %>
<div class="media">
<div class="mediabox">
<div class="media-left" href="#">
<!-- <img class="media-object" src="..." alt="Generic placeholder image">-->
<% if f.photos.first %>
<%= image_tag f.photos.first.image.url , :class => "media-object"%>
<%end%>
</div>
<div class="media-body">
<h5 class="media-heading"> <%= f.title %></h5>
<small><%= f.created_month %></small>
<% if f.category.parent_id? %>
<small><%= f.category.root.name %></small>
<%end%>
<small><%= f.category.name %></small>
<div class="price ">
<h5><%= f.price %> </h5>
</div>
</div>
</div>
</div>
</div>
</div>
<%end%>
<%end%>
<%end%>
<%end%>
</div>
im a noob , i know there's stuff wrong with my indentation in html , sorry for that!
Ok i did it by nesting routes and taking some fields from the categories model.
resources :categories do
resources :classifieds do
end
end
Category model:
def nested_classifieds
Classified.where(category_id: self_and_descendants.select(:id))
end
def nested_categories
self_and_descendants
end
Classifieds controller
def index
if #category.present?
#classifieds = #category.nested_classifieds
nested_categories = []
#category.nested_categories.each do |f|
nested_categories << f.id
end
#search = Sunspot.search(Classified ) do
paginate(:page => params[:page] || 1, :per_page => 10)
order_by(:created_at , :desc)
fulltext params[:search]
with(:categoryid,nested_categories)
active_model = with(:model ,params[:model]) if params[:model].present?
active_make = with(:make , params[:make]) if params[:make].present?
active_make_country = with(:make_country , params[:make_country]) if params[:make_country].present?
active_condition = with(:condition,params[:condition]) if params[:condition].present?
active_category = with(:cat,params[:cat]) if params[:cat].present?
active_subcategory = with(:treecat,params[:treecat]) if params[:treecat].present?
active_pricerange = with(:price, params[:price]) if params[:price].present?
fulltext params[:prc]
facet :price
with(:price).less_than(1000)
facet(:model)
#facet(:model , exclude: active_condition)
facet(:make)
facet(:make_country)
facet(:condition)
facet(:cat)
facet(:treecat)
end
#classifieds = #search.results
else
#redirect_to '/'
##classified=#search.results
search
end
end

Smart_listing Gem sorting

Im integrating Smart_listing gem onto my Rails App. I have a Beer table in my database and a beer_type column. Right now im trying to set up a sorting function where Users can filter different types of beer. Similar to this functionality example.
Right now it will filter each one type of beer perfectly. However whenever there is more than 1 beer type checked, it would not display the beer types together.
product.rb
scope :with_beer_type_ales, -> (product) { where('beer_type ILIKE?', "%ales%") }
scope :with_beer_type_cream, -> (product) { where('beer_type ILIKE?', "%cream%") }
scope :like, ->(args) { where("name ILIKE? OR beer_type ILIKE? OR description ILIKE?", "%#{args}%", "%#{args}%", "%#{args}%")}
products_controller.rb
def index
products_scope = Product.all
# Make users initally sorted by name ascending
products_scope = products_scope.like(params[:filter]) if params[:filter]
products_scope=products_scope.with_beer_type_ales(params[:with_beer_type_ales]) if params[:with_beer_type_ales] == "1"
products_scope = products_scope.with_beer_type_cream(params[:with_beer_type_cream]) if params[:with_beer_type_cream] == "1"
#products = smart_listing_create :products,
products_scope,
partial: "products/list",
page_sizes: [10, 20, 30],
default_sort: {name: "asc"}
end
index.html.erb
<%= smart_listing_controls_for(:products, {class: "form-inline text-left"}) do %>
<div class="form-group filter input-append" id="search">
<%= text_field_tag :filter, '', class: "search form-control",
placeholder: "Search...", autocomplete: :off %>
<button class="btn btn-primary disabled" type="<%= :submit %>">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
<h4>Sort By Type:</h4>
<ul>
<li class="checkbox">
<label class="checkbox inline">
<%= hidden_field_tag :with_beer_type_ales, "0" %>
<%= check_box_tag :with_beer_type_ales %> Ales
</label>
</li>
<li>
<label class="checkbox inline">
<%= hidden_field_tag :with_beer_type_cream, "0" %>
<%= check_box_tag :with_beer_type_cream %> Cream
</label>
</li>
</ul>
</div>
<% end %>
You want OR not AND. When you specify multiple where clauses in a chain, rails defaults to AND.
q = Beer.where(true)
q = q.or.where('beer_type ILIKE?', "%ales%") if params[:with_beer_type_ales] == "1"
q = q.or.where('beer_type ILIKE?', "%cream%") if params[:with_beer_type_cream] == "1"

Can't display all products

i'm working on a Rails application with Spree Commerce.
I'm trying to display all products in a taxon cause i'm using them not as category but as some kind of registry.
So, i'm editing /app/views/spree/taxons/show.html.erb. Especifically this line:
<%= render partial: 'spree/shared/products', locals: { products: #products, taxon: #taxon } %>
Changing it for:
<%= render :partial => 'spree/shared/products', :locals => { :products => #products } %>
But it still says "No products found". But in my index they are showed.
So, How can I properly show all products?
Thanks in advance.
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
Rails 4.2.5
Spree 3.0.4
As requested:
1) This is the show from products
<% #body_id = 'product-details' %>
<% cache [I18n.locale, current_currency, #product, #product.possible_promotions] do %>
<div data-hook="product_show" itemscope itemtype="https://schema.org/Product">
<div class="col-md-4" data-hook="product_left_part">
<div data-hook="product_left_part_wrap">
<div id="product-images" data-hook="product_images">
<div id="main-image" class="panel panel-default" data-hook>
<div class="panel-body text-center">
<%= render :partial => 'image' %>
</div>
</div>
<div id="thumbnails" data-hook>
<%= render :partial => 'thumbnails' %>
</div>
</div>
<div data-hook="product_properties">
<%= render :partial => 'properties' %>
</div>
<div data-hook="promotions">
<%= render :partial => 'promotions' %>
</div>
</div>
</div>
<div class="col-md-8" data-hook="product_right_part">
<div data-hook="product_right_part_wrap">
<div id="product-description" data-hook="product_description">
<h1 class="product-title" itemprop="name"><%= #product.name %></h1>
<div class="well" itemprop="description" data-hook="description">
<%= product_description(#product) rescue Spree.t(:product_has_no_description) %>
</div>
<div id="cart-form" data-hook="cart_form">
<%= render :partial => 'cart_form' %>
</div>
</div>
<%= render :partial => 'taxons' %>
</div>
</div>
</div>
<% end %>
2) Show from taxons
<h1 class="taxon-title"><%= #taxon.name %></h1>
<% content_for :sidebar do %>
<div data-hook="taxon_sidebar_navigation">
<%= render partial: 'spree/shared/taxonomies' %>
<%= render partial: 'spree/shared/filters' if #taxon.leaf? %>
</div>
<% end %>
<div data-hook="taxon_products">
<%= render partial: 'spree/shared/products', locals: { products: #products, taxon: #taxon } %>
</div>
<% unless params[:keywords].present? %>
<div data-hook="taxon_children">
<% cache [I18n.locale, #taxon] do %>
<%= render partial: 'taxon', collection: #taxon.children %>
<% end %>
</div>
<% end %>
3) This is how I render in my index
<div data-hook="homepage_products">
<% cache(cache_key_for_products) do %>
<%= render :partial => 'spree/shared/products', :locals => { :products => #products } %>
<% end %>
</div>
4) _products.html.erb
<%
paginated_products = #searcher.retrieve_products if params.key?(:keywords)
paginated_products ||= products
%>
<% content_for :head do %>
<% if paginated_products.respond_to?(:num_pages) %>
<%= rel_next_prev_link_tags paginated_products %>
<% end %>
<% end %>
<div data-hook="products_search_results_heading">
<% if products.empty? %>
<div data-hook="products_search_results_heading_no_results_found">
<%= Spree.t(:no_products_found) %>
</div>
<% elsif params.key?(:keywords) %>
<div data-hook="products_search_results_heading_results_found">
<h6 class="search-results-title"><%= Spree.t(:search_results, keywords: h(params[:keywords])) %></h6>
</div>
<% end %>
</div>
<% if products.any? %>
<div id="products" class="row" data-hook>
<% products.each do |product| %>
<% url = spree.product_url(product, taxon_id: #taxon.try(:id)) %>
<div id="product_<%= product.id %>" class="col-md-3 col-sm-6 product-list-item" data-hook="products_list_item" itemscope itemtype="https://schema.org/Product">
<div class="panel panel-default">
<% cache(#taxon.present? ? [I18n.locale, current_currency, #taxon, product] : [I18n.locale, current_currency, product]) do %>
<div class="panel-body text-center product-body">
<%= link_to small_image(product, itemprop: "image"), url, itemprop: 'url' %><br/>
<%= link_to truncate(product.name, length: 50), url, class: 'info', itemprop: "name", title: product.name %>
</div>
<div class="panel-footer text-center">
<span itemprop="offers" itemscope itemtype="https://schema.org/Offer">
<span class="price selling lead" itemprop="price"><%= display_price(product) %></span>
</span>
</div>
<% end %>
</div>
</div>
<% end %>
<% reset_cycle("classes") %>
</div>
<% end %>
<% if paginated_products.respond_to?(:num_pages) %>
<%= paginate paginated_products, theme: 'twitter-bootstrap-3' %>
<% end %>
Controller index:
module Spree
class HomeController < Spree::StoreController
helper 'spree/products'
respond_to :html
def index
#searcher = build_searcher(params.merge(include_images: true))
#products = #searcher.retrieve_products
#taxonomies = Spree::Taxonomy.includes(root: :children)
end
end
end
Go to spree/frontend/app/controllers/spree/taxons_controller.rb
make the show method look like this
def show
#taxon = Taxon.friendly.find(params[:id])
return unless #taxon
#searcher = build_searcher(params.merge(include_images: true))
#products = #searcher.retrieve_products
#taxonomies = Spree::Taxonomy.includes(root: :children)
end
First of, your file should be called _products.html.erb.
But it still says "No products found"
Second, could you please show us this file?
But in my index they are showed.
Could you also show us how you render your products in your index?
EDIT: It seems like in Taxons#show, the #products instance variable is not set. Check if you set it in the show action in your TaxonsController.
Actually I am looking for an answer to "No products found"
Here is my question link:
Spree Commerce: No Products Found
Spree Commerce: No Products Found
I have just joined stackoverflow.com a couple of minutes, can't add a comment to above answers.
Here is /controllers/spree/taxons_controller.rb:
module Spree
class TaxonsController < Spree::StoreController
rescue_from ActiveRecord::RecordNotFound, with: :render_404
helper 'spree/products'
respond_to :html
def show
#taxon = Taxon.friendly.find(params[:id])
return unless #taxon
#searcher = build_searcher(params.merge(taxon: #taxon.id, include_images: true))
sorting_scope = params[:order].try(:to_sym) || :ascend_by_updated_at
#taxonomies = Spree::Taxonomy.includes(root: :children)
#searcher.retrieve_products
#products = #searcher.retrieve_products
#curr_page = params[:page] || 1
#products_per_page = Spree::Config.products_per_page
#start_no = #curr_page == 1 ? 1 : ((#curr_page.to_i-1)*#products_per_page)+1
#end_no = #products.length
if #curr_page.to_i > 1
#end_no = ( (#curr_page.to_i-1)*#products_per_page) + #end_no
end
# #end_no = #product_count <= #product_count ? #product_count : #products.length+(#curr_page.to_i-1)*#products_per_page
end
private
def accurate_title
#taxon.try(:seo_title) || super
end
end
end

Agenda calendar/roster view

I would like to display an agenda that shows who is available for roster for the next seven days, with the following logic:
Looping through each of the 7 days, for each day:
If the leave starts today, show Starts %H:%M
If the leave finishes today, show Finishes %H:%M
If the leave starts and finishes today, show %H:%M - %H:%M
If the leave doesn't start or finish today but spans over today, show all day
Should include leave that start or finish outside of the 7 days but span the 7 days being displayed.
I am hoping for someone to point me in the right direction preferably using Rails and Postgres. I am not against doing the queries for each day since at most there will only be 30 days displayed, but also looking for reasonably performant code since there could be 100+ leave records per day.
First example that does not fulfill the criteria outlined above.
<% #dates.each do |d| %>
<h5><%= d.strftime("%A %d %b") %></h5>
<% #leave = Leave.where('(start_at BETWEEN ? AND ?) OR (end_at BETWEEN ? AND ?)', d.beginning_of_day, d.end_of_day, d.beginning_of_day, d.end_of_day) %>
<% #leave = #leave.where.not('end_at < ?', Time.current) %>
<% if #leave.any? %>
<ul>
<% #leave.each do |leave| %>
<% if leave.single_day? && leave.start_at.to_date == d %>
<li>
<label class="label label-danger"><%= leave.start_at.strftime('%H:%M') %> - <%= leave.end_at.strftime('%H:%M') %></label>
<%= leave.user.name %>
</li>
<% elsif !leave.single_day? %>
<% if leave.start_at.to_date == d %>
<li>
<label class="label label-danger">From <%= leave.start_at.strftime('%H:%M') %></label>
<%= leave.user.name %>
</li>
<% elsif leave.end_at.to_date == d %>
<li>
<label class="label label-danger">Until <%= leave.end_at.strftime('%H:%M') %></label>
<%= leave.user.name %>
</li>
<% else %>
<li>
<label class="label label-danger">All Day</label>
<%= leave.user.name %>
</li>
<% end %>
<% end %>
<% end %>
</ul>
<br/>
<span class="label label-success" style="margin-right: 10px;">
<span class="glyphicon glyphicon-ok"></span>
</span>
<%= current_account.users.active.where.not(id: #leave.map(&:user_id)).count %> Available
<% else %>
<span class="label label-success" style="margin-right: 10px;">
<span class="glyphicon glyphicon-ok"></span>
</span>
<%= current_account.users.active.count %> Available
<% end %>
<br />
<br />
<% end %>
I would start with something like this:
In the model:
def starts_on?(date)
start_at.to_date == date
end
def ends_on?(date)
end_at.to_date = date
end
def covers?(date)
leave.start_at.to_date <= date && leave.end_at.to_date >= date
end
def starts_and_ends_on?(date)
starts_on?(date) && ends_on?(date)
end
In the controller:
#dates = # define the date range like you already do, I assume it is an array
#leaves = Leave.includes(:user).
where('start_at =< ? AND end_at >= ?', dates.max, dates.min)
In the helper:
def relevant_leaves_for_date(date, leaves)
leaves.select { |leave| leave.covers?(date) }
end
def leave_description_for_date(leave, date)
if leave.starts_and_ends_on?(date)
"#{leave.start_at.strftime('%H:%M')} - #{leave.end_at.strftime('%H:%M')}"
elsif leave.starts_on?(date)
"From #{leave.start_at.strftime('%H:%M')}"
elsif leave.ends_on?(date)
"Until #{leave.end_at.strftime('%H:%M')}"
else
'All day'
end
end
def available_users(leaves)
current_account.users.active.count - leaves.size
end
In the view:
<% #dates.each do |date| %>
<h5><%= date.strftime("%A %d %b") %></h5>
<% leaves = relevant_leaves_for_date(date, #leaves) %>
<% if leaves.any? %>
<ul>
<% leaves.each do |leave| %>
<li>
<label class="label label-danger">
<%= leave_description_for_date(leave, date) %>
</label>
<%= leave.user.name %>
</li>
<% end %>
</ul>
<% end %>
<span class="label label-success">
<span class="glyphicon glyphicon-ok"></span>
</span>
<%= available_users(leaves) %> Available
<% end %>
You might notice that I remove the <br> and style tags from the html. Please do not use <br> for styling or style attributes in the html. Add class the the tags and style them in your css file.
The reason why case 4 & 5 are not working is you are not fetching the leaves which started before the beginning of day or which are going to end after the end of day. So you can fetch all leaves which have not ended yet.
<% #leave = Leave.where('(end_at >= ?', d.beginning_of_day) %>
And then in application_helper.rb, you can have a function like this,
def check_for_leave(leave,d)
msg = ""
if leave.single_day? && leave.start_at.to_date == d
msg = "#{leave.start_at.strftime('%H:%M')} - #{leave.end_at.strftime('%H:%M')}"
elsif !leave.single_day?
if leave.start_at.to_date == d
msg = "From #{leave.start_at.strftime('%H:%M')}"
elsif leave.end_at.to_date == d
msg = "Until #{leave.end_at.strftime('%H:%M')}"
else
msg = "All Day"
end
return msg
end
In html.erb file
<% #dates.each do |d| %>
<h5><%= d.strftime("%A %d %b") %></h5>
<% #leave = Leave.where('(end_at >= ?', d.beginning_of_day) %>
<% if #leave.any? %>
<ul>
<% #leave.each do |leave| %>
<li>
<label class="label label-danger">
<%= check_for_leave(leave, d) %>
</label>
<%= leave.user.name %>
</li>
<% end %>
</ul>
<br/>
<span class="label label-success" style="margin-right: 10px;">
<span class="glyphicon glyphicon-ok"></span>
</span>
<%= current_account.users.active.where.not(id: #leave.map(&:user_id)).count %> Available
<% else %>
<span class="label label-success" style="margin-right: 10px;">
<span class="glyphicon glyphicon-ok"></span>
</span>
<%= current_account.users.active.count %> Available
<% end %>
<br />
<br />
<% end %>

passing dynamic variable to partial for rendering in a modal

I have the following Code on a partial that dynamically generates a list of associated steps to a pin. Both pins and steps have image(s). Users are able to add multiple steps to a pin and then this view dynamically generates a view of these steps. For each step there are associated image(s) which I'd like to pop-up as a modal. The challenge is I keep getting the following error:
"undefined local variable or method `step' for #<#:0x00000102f498d8>"
When I stub out rendering the partial, the modal appears basically blank but works. Any ideas How do I do this?
<div class="col-md-6">
<% (0..(Step.where("pin_id = ?", params[:id]).count)-1).each do |step| %>
<div class="col-md-12">
<div class="well">
<ul class="nav pull-right">
<% if current_user == #pin.user %>
<%= link_to edit_step_path((Step.where("pin_id = ?", params[:id]).fetch(step)), :pin_id => #pin.id) do %>
<span class="glyphicon glyphicon-edit"></span>
Edit
<% end %> |
<%= link_to Step.where("pin_id = ?", params[:id]).fetch(step), method: :delete, data: { confirm: 'Are you sure?' } do %>
<span class="glyphicon glyphicon-trash"></span>
Delete
<% end %> |
<%= link_to new_step_image_path(:step_id => Step.where("pin_id = ?", params[:id]).fetch(step), :pin_id => #pin.id) do %>
Add
<span class="glyphicon glyphicon-picture"></span>
<% end %>
<% end %>
<% if StepImage.where("step_id = ?", Step.where("pin_id = ?", params[:id]).pluck(:id).fetch(step)).count == 0 %>
<% else %>
| <a href="#StepImageModal" data-toggle="modal">
<span class="glyphicon glyphicon-picture"></span> (<%= StepImage.where("step_id = ?", Step.where("pin_id = ?", params[:id]).pluck(:id).fetch(step)).count %> ) </strong>
</a>
<% end %>
</ul>
<strong> Step <%= step+1 %>
<p>
<%= Step.where("pin_id = ?", params[:id]).pluck(:description).fetch(step) %>
</p>
</div>
</div>
<%end %>
</div>
<div class="modal fade" id="StepImageModal">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>Modal Header</h3>
</div>
<div class="modal-body">
<%= render :partial => 'pins/step_images',
:locals => { :step => step } %>
</div>
<div class="modal-footer">
Close
</div>
</div>
I don't get what you're trying to do here
Loop
As mentioned in the comments, you've got a loop which goes through your steps. However, outside the loop, you want to display the partial
The solution to your woes will either be to set an instance variable (not desired), or use another persistent data type. I'd do this:
#app/controllers/steps_controller.rb
def action
#step = {}
end
#app/views/steps/action.html.erb
<% (0..(Step.where("pin_id = ?", params[:id]).count)-1).each do |step| %>
<% #step[step.id.to_sym] = step.details %>
<% end %>
<%= render :partial => 'pins/step_images', :locals => { :step => #step } %>
unless
Some refactoring for you:
<% unless StepImage.where("step_id = ?", Step.where("pin_id = ?", params[:id]).pluck(:id).fetch(step)).count == 0 %>
| <%= link_to "#StepImageModal", data: { toggle: "modal"} do %>
<span class="glyphicon glyphicon-picture"></span>(<%= StepImage.where("step_id = ?", Step.where("pin_id = ?", params[:id]).pluck(:id).fetch(step)).count %> ) </strong>
<% end %>
<% end %>

Resources