real time broadcasting in not working in rails 7 - ruby-on-rails

I have added broadcasting in the rails model, please have a look at the below files
.
Comment model
class Comment < ApplicationRecord
validates :body, presence: true
belongs_to :post
after_create_commit { broadcast_append_to "comments_#{self.post_id}", partial: "posts/comment" }
end
Post model
class Post < ApplicationRecord
has_many :comments, dependent: :destroy
end
app/views/posts/index.html.erb
<h1 class="text-center m-4 text-success">Posts</h1>
<div id="posts">
<div class="row">
<% #posts.each do |post| %>
<%= render post %>
<% end %>
</div>
</div>
app/views/posts/_post.html.erb
<div class="col-lg-4 mb-2">
<div class="card border-0" style="width: 18rem;">
<div class="card-body">
<p>
<span class="comment">
<%= link_to fa_icon("comment"),"#", data: { action: "click->like#comment",comment_url: new_post_comment_path(post.id) } %>
</span>
</p>
<div id="add_comment_<%= post.id %>"></div>
<h5 class="card-title"><%= post.title %></h5>
<p class="card-text"><%= post.description %></p>
<strong>Comments</strong>
<%= turbo_stream_from "comments_#{post.id}" %>
<%= turbo_frame_tag "comments_#{post.id}" do %>
<div id="add_comments_<%= post.id %>">
<% post.comments.each do |comment_post| %>
<%= render partial: "posts/comment", locals: { comment: comment_post } %>
<% end %>
</div>
<% end %>
</div>
</div>
</div>
app/views/posts/_comment.html.erb
<p id="comment_<%= comment.id %>" data-controller="comment"><%= comment.body %>
<span>
<%= link_to "edit",post_comment_edit_path(comment.post,comment), data: { turbo_method: :post } %>
</span>
<span><%= link_to "delete", post_comment_path(comment.post,comment), data: { turbo_method: :delete } %></span>
<span><%= commentUpdatedAt(comment) %> ago</span>
</p>
I have checked with binding.pry, in the comment model does not get post_id when creating a comment, so the targets are different.
Please help me

I have found the above answer,
app/models/comment.rb file
class Comment < ApplicationRecord
validates :body, presence: true
belongs_to :post
belongs_to :user
after_create_commit :set_comment
after_update_commit :update_comment
after_destroy_commit :destroy_comment
private
def set_comment
broadcast_append_to "add_comments_#{self.post.id}", partial: "posts/comment", target: "add_comments_#{self.post.id}"
end
def update_comment
broadcast_update_to "comment_#{self.id}", partial: "posts/comment", target: "comment_#{self.id}"
end
def destroy_comment
broadcast_remove_to "comment_#{self.id}"
end
end
app/views/posts/_post.html.erb file
<strong>Comments</strong>
<%= turbo_stream_from "add_comments_#{post.id}" %>
<div id="add_comments_<%= post.id %>">
<% post.comments.each do |comment_post| %>
<%= render partial: "posts/comment", locals: { comment: comment_post } %>
<% end %>
</div>
app/views/posts/_comment.html.erb file
<%= turbo_stream_from "comment_#{comment.id}" %>
<p id="comment_<%= comment.id %>" data-controller="comment"><%= comment.body %>
<span>
<%= link_to "edit",post_comment_edit_path(comment.post,comment), data: { turbo_method: :post } %>
</span>
<span><%= link_to "delete", post_comment_path(comment.post,comment), data: { turbo_method: :delete } %></span>
<span>
<%= link_to "reply",replyComment_post_comment_index_path(comment.post), data: { turbo_method: :post } %>
</span>
<span><%= commentUpdatedAt(comment) %> ago</span>
</p>
The solution is working well as I expected.

Related

Ordering by category id and price on index page

I’m having trouble with ordering my houses. I have a houses that belong_to category (category has_many houses) and I want to order the houses on the index based on their category_id, but whatever I try it doesn’t seem to change the order. It’s a mystery to me. Maybe you could help me out?
class HousesController < ApplicationController
skip_before_action :authenticate_user!, only: [:index, :show]
before_action :set_house, only: [ :show, :edit, :update, :destroy, :inquiry ]
​
def index
# byebug
#houses = policy_scope(House).order(:name)
#houses = params.has_key?(:h) ? index_result(#houses) : #houses
# split_categories(#houses)
end
​
def index_result(houses)
# byebug
wall_thickness = params[:h].to_i
if wall_thickness == 1
houses.order(:name)
render "results_index_all"
elsif wall_thickness == 28 || 40
houses = houses.where(:wall => wall_thickness)
houses.order(:name)
render "results_index"
else
end
end
​
def split_categories(houses)
# #houses_1 = #houses.where(price_cents: 0...260000)
# #houses_2 = #houses.where(price_cents: 260000..1000000)
# byebug
category = Category.find_by(id: params[:category])
houses = #category.present? ? category.houses.order(price_cents: :asc) : houses
end
​
def show
end
​
def new
#house = House.new
authorize #house
end
​
def create
#house = House.new(house_params)
#house.user = current_user
authorize #house
if #house.save
redirect_to house_path(#house)
else
render :new
end
end
​
def edit
end
​
def update
if #house.update(house_params)
redirect_to house_path(#house)
else
render :edit
end
end
​
def destroy
#house.destroy
redirect_to root_path
end
​
private
​
def set_house
#house = House.friendly.find(params[:id])
authorize #house
end
​
def house_params
params.require(:house).permit(:sku, :name, :price_cents, :width, :length, :wall, pictures: [])
end
​
end
Below is the normal index where I split houses up in categories starting with category_id: 2 (normal garden houses), then 1 (gazebos) and finally 3 (garages). This is partial which is rendered app/views/houses/index.html.erb
<% if !#category %>
<%= render 'first-banner-home' %>
<div class="container catalog">
<%= render "filter_buttons" %>
<div class="row">
<% #houses.where(category_id: 2).each do |house| %>
<div class="col-sm-6 col-md-4">
<div class="card">
<% if house.pictures? %>
<div class="imageTop" style="position: relative;">
<%= cl_image_tag(house.pictures[0], :quality=>50, :width=>1800, :crop=>"scale", class: "card-img-top", alt: house.name + " " + house.category.name) %>
<%= link_to "", house_path(house), class: "card-link" %>
</div>
<% end %>
<div class="card-body indexBody">
<div class="card-price">
<h3 class="card-title"><%= house.name %></h3>
<h3><%= house.length.to_f / 100 %> x <%= house.width.to_f.to_f / 100 %> m</h3>
</div>
<div class="card-price">
<% if house.price_present == false %>
<h3><%= t('show.consult') %></h3>
<% else %>
<h3><%= humanized_money_with_symbol(house.original_price) %><span style="color: red"> - 15%</span> = <%= humanized_money_with_symbol(house.price) %></h3>
<% end %>
</div>
<% if policy(house).update? %>
<%= link_to "Edit", edit_house_path(house) %>
<% end %>
<% if policy(house).destroy? %>
<%= link_to "Remove", house_path(house), method: :delete, data: { confirm: "Are you sure?" } %>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<div class="container catalog">
<h3><%= t('home.gazebos') %></h3>
<div class="row">
<% #houses.where(category_id: 1).each do |house| %>
<div class="col-sm-6">
<div class="card">
<% if house.pictures? %>
<div class="imageTop" style="position: relative;">
<%= cl_image_tag(house.pictures[0], :quality=>50, :width=>1800, :crop=>"scale", class: "card-img-top-alt", alt: house.name + " " + house.category.name) %>
<%= link_to "", house_path(house), class: "card-link" %>
</div>
<% end %>
<div class="card-body indexBody">
<div class="card-price">
<h3 class="card-title"><%= house.name %></h3>
<h3><%= house.length.to_f / 100 %> x <%= house.width.to_f.to_f / 100 %> m</h3>
</div>
<div class="card-price">
<% if house.price_present == false %>
<h3><%= t('show.consult') %></h3>
<% else %>
<h3><%= humanized_money_with_symbol(house.original_price) %><span style="color: red"> - 15%</span> = <%= humanized_money_with_symbol(house.price) %></h3>
<% end %>
</div>
<% if policy(house).update? %>
<%= link_to "Edit", edit_house_path(house) %>
<% end %>
<% if policy(house).destroy? %>
<%= link_to "Remove", house_path(house), method: :delete, data: { confirm: "Are you sure?" } %>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<div class="container catalog">
<h3><%= t('home.garages') %></h3>
<div class="row">
<% #houses.where(category_id: 3).each do |house| %>
<div class="col-sm-6">
<div class="card">
<% if house.pictures? %>
<div class="imageTop" style="position: relative;">
<%= cl_image_tag(house.pictures[0], :quality=>50, :width=>1800, :crop=>"scale", class: "card-img-top-alt", alt: house.name + " " + house.category.name) %>
<%= link_to "", house_path(house), class: "card-link" %>
</div>
<% end %>
<div class="card-body indexBody">
<div class="card-price">
<h3 class="card-title"><%= house.name %></h3>
<h3><%= house.length.to_f / 100 %> x <%= house.width.to_f.to_f / 100 %> m</h3>
</div>
<div class="card-price">
<% if house.price_present == false %>
<h3><%= t('show.consult') %></h3>
<% else %>
<h3><%= humanized_money_with_symbol(house.original_price) %><span style="color: red"> - 15%</span> = <%= humanized_money_with_symbol(house.price) %></h3>
<% end %>
</div>
<% if policy(house).update? %>
<%= link_to "Edit", edit_house_path(house) %>
<% end %>
<% if policy(house).destroy? %>
<%= link_to "Remove", house_path(house), method: :delete, data: { confirm: "Are you sure?" } %>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<%= render "last-banner" %>
<% elsif params[:h].present? %>
<%= render "results_index" %>
<% else %>
<%= render "category_index" %>
<% end %>
This is the index where the houses are filtered based on their wall thickness (see in app/controllers/houses_controller.rb ). This is where I want the house to order based on their category_id, which doesn’t work at the moment.
<% content_for(:title) do %><%= t('topbar.brand') %><% end %>
<% content_for(:og_site_name) do %><%= t('topbar.brand') %><% end %>
<% content_for(:description) do %><%= t('garden_houses.meta_description') %><% end %>
<% content_for(:og_image) do %><%= cl_image_path("https://res.cloudinary.com/www-ibizagardenhouses-com/image/upload/c_scale,h_630,w_1200/v1558696079/ibi-3/image.jpg") %><% end %>
<% content_for(:og_description) do %><%= t('garden_houses.meta_description') %><% end %>
<%= render 'first-banner-results' %>
<% if #houses.count >= 4 %>
<div class="container catalog">
<%= render "filter_buttons" %>
<div class="row">
<% #houses.each do |house| %>
<div class="col-sm-6 col-md-4">
<div class="card">
<% if house.pictures? %>
<div class="imageTop" style="position: relative;">
<%= cl_image_tag(house.pictures[0], :quality=>50, :width=>1800, :crop=>"scale", class: "card-img-top", alt: house.name + " " + house.category.name) %>
<%= link_to "", house_path(house), class: "card-link" %>
</div>
<% end %>
<div class="card-body indexBody">
<div class="card-price">
<h3 class="card-title"><%= house.name %></h3>
<h3><%= house.length.to_f / 100 %> x <%= house.width.to_f.to_f / 100 %> m</h3>
</div>
<div class="card-price">
<% if house.price_present == false %>
<h3><%= t('show.consult') %></h3>
<% else %>
<h3><%= humanized_money_with_symbol(house.original_price) %><span style="color: red"> - 15%</span> = <%= humanized_money_with_symbol(house.price) %></h3>
<% end %>
</div>
<% if policy(house).update? %>
<%= link_to "Edit", edit_house_path(house) %>
<% end %>
<% if policy(house).destroy? %>
<%= link_to "Remove", house_path(house), method: :delete, data: { confirm: "Are you sure?" } %>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<%= render "last-banner" %>
<% else %>
<div class="container catalog">
<%= render "filter_buttons" %>
<div class="row">
<% #houses.each do |house| %>
<div class="col-sm-6">
<div class="card">
<% if house.pictures? %>
<div class="imageTop" style="position: relative;">
<%= cl_image_tag(house.pictures[0], :quality=>50, :width=>1800, :crop=>"scale", class: "card-img-top-alt", alt: house.name + " " + house.category.name) %>
<%= link_to "", house_path(house), class: "card-link" %>
</div>
<% end %>
<div class="card-body indexBody">
<div class="card-price">
<h3 class="card-title"><%= house.name %></h3>
<h3><%= house.length.to_f / 100 %> x <%= house.width.to_f.to_f / 100 %> m</h3>
</div>
<div class="card-price">
<% if house.price_present == false %>
<h3><%= t('show.consult') %></h3>
<% else %>
<h3><%= humanized_money_with_symbol(house.original_price) %><span style="color: red"> - 15%</span> = <%= humanized_money_with_symbol(house.price) %></h3>
<% end %>
</div>
<% if policy(house).update? %>
<%= link_to "Edit", edit_house_path(house) %>
<% end %>
<% if policy(house).destroy? %>
<%= link_to "Remove", house_path(house), method: :delete, data: { confirm: "Are you sure?" } %>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<%= render "last-banner" %>
<% end %>
This is exactly the same html as app/views/houses/results_index.html.erb , but where I show all the houses (params[h: 1]) in a layout that’s not the same as the home page. Same problem here as on the filtered results page.
<% content_for(:title) do %><%= t('topbar.brand') %><% end %>
<% content_for(:og_site_name) do %><%= t('topbar.brand') %><% end %>
<% content_for(:description) do %><%= t('garden_houses.meta_description') %><% end %>
<% content_for(:og_image) do %><%= cl_image_path("https://res.cloudinary.com/www-ibizagardenhouses-com/image/upload/c_scale,h_630,w_1200/v1558696079/ibi-3/image.jpg") %><% end %>
<% content_for(:og_description) do %><%= t('garden_houses.meta_description') %><% end %>
<%= render 'first-banner-all' %>
<% if #houses.count >= 4 %>
<div class="container catalog">
<%= render "filter_buttons" %>
<div class="row">
<% #houses.each do |house| %>
<div class="col-sm-6 col-md-4">
<div class="card">
<% if house.pictures? %>
<div class="imageTop" style="position: relative;">
<%= cl_image_tag(house.pictures[0], :quality=>50, :width=>1800, :crop=>"scale", class: "card-img-top", alt: house.name + " " + house.category.name) %>
<%= link_to "", house_path(house), class: "card-link" %>
</div>
<% end %>
<div class="card-body indexBody">
<div class="card-price">
<h3 class="card-title"><%= house.name %></h3>
<h3><%= house.length.to_f / 100 %> x <%= house.width.to_f.to_f / 100 %> m</h3>
</div>
<div class="card-price">
<% if house.price_present == false %>
<h3><%= t('show.consult') %></h3>
<% else %>
<h3><%= humanized_money_with_symbol(house.original_price) %><span style="color: red"> - 15%</span> = <%= humanized_money_with_symbol(house.price) %></h3>
<% end %>
</div>
<% if policy(house).update? %>
<%= link_to "Edit", edit_house_path(house) %>
<% end %>
<% if policy(house).destroy? %>
<%= link_to "Remove", house_path(house), method: :delete, data: { confirm: "Are you sure?" } %>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<%= render "last-banner" %>
<% else %>
<div class="container catalog">
<%= render "filter_buttons" %>
<div class="row">
<% #houses.each do |house| %>
<div class="col-sm-6">
<div class="card">
<% if house.pictures? %>
<div class="imageTop" style="position: relative;">
<%= cl_image_tag(house.pictures[0], :quality=>50, :width=>1800, :crop=>"scale", class: "card-img-top-alt", alt: house.name + " " + house.category.name) %>
<%= link_to "", house_path(house), class: "card-link" %>
</div>
<% end %>
<div class="card-body indexBody">
<div class="card-price">
<h3 class="card-title"><%= house.name %></h3>
<h3><%= house.length.to_f / 100 %> x <%= house.width.to_f.to_f / 100 %> m</h3>
</div>
<div class="card-price">
<% if house.price_present == false %>
<h3><%= t('show.consult') %></h3>
<% else %>
<h3><%= humanized_money_with_symbol(house.original_price) %><span style="color: red"> - 15%</span> = <%= humanized_money_with_symbol(house.price) %></h3>
<% end %>
</div>
<% if policy(house).update? %>
<%= link_to "Edit", edit_house_path(house) %>
<% end %>
<% if policy(house).destroy? %>
<%= link_to "Remove", house_path(house), method: :delete, data: { confirm: "Are you sure?" } %>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<%= render "last-banner" %>
<% end %>
As you can see, there's a lot of duplication of code (not very DRY) and so I'd like a little help in getting more DRY and have the houses be ordered by category_id and then by price.
I'd appreciate your help.
It's not clear to me what you tried so far, but if all you need is to sort by category_id, I think you can define a scope within your house model as follow:
scope :sort_by_category_id_asc, ->{
order(arel_table[:category_id].asc)
}
Then you can use that scope as follow: House.where(...).sort_by_category_id_asc, also you can use desc, depends on how you want to order the result.
Hope this helps! 👍
I created a method that can sort houses by its category_id. If you want to sort it by other things just change category_id to your desired thing. You can sort it ascending or descending order. Here it is:
def sort_by_category_id(houses, order)
case order_by
when "asc"
houses = houses.sort_by{ |house|
house[:category_id]
}
when "desc"
house= house.sort_by{ |house|
house[:category_id]
}.reverse!
end
house
end
Don't forget to call this method wherever you want it to be worked. Below code will sort your houses by category_id and save it in sorted_houses variable. I
sorted_houses_asc = sort_by_category_id(#houses, "asc")
sorted_houses_desc = sort_by_category_id(#houses, "desc")
Hope this helped you somehow.

acts-as-taggable-on gem is not persisting tag strings into edit or into show

I have tags on my video objects. I can submit tags when creating a new video via my form however they don't appear on my video show page, video index or video edit form, which makes me think they are not being presisted to the database but I'm unclear on what I as missing or doing wrong.
models/video.rb
class Video < ActiveRecord::Base
after_create { validates_presence_of :user, :post }
belongs_to :user
belongs_to :post
has_many :comments
validates :title, presence: true
acts_as_taggable
end
views/videos/index.html.erb
<%= will_paginate #videos %>
<div class="" id="tag_cloud">
<% tag_cloud Video.tag_counts.sort { |x, y| x.name <=> y.name }, %w[s m l] do |tag, css_class| %>
<%= link_to tag.name, tag_path(tag.name), class: css_class %>
<% end %>
</div>
<div class="">
<% #videos.each do |video| %>
<div class="">
<%= link_to video.title, video_path(video) %></br >
<%= content_tag(:iframe, nil, src: "//www.youtube.com/embed/#{video.embed_id}") %>
<p>Created by: <%= video.user.username %>, at: <%= video.created_at.strftime("%e, %b, %Y, %H:%M:%S %p") %></p>
<% unless video.comments.last.nil? %>
<%= video.comments.last.body %>
<% end %>
<p>
Tags: <%= raw video.tag_list.map { |t| link_to t, tag_path(t) }.join(", ") %>
</p>
<% end %>
</div>
</div>
views/videos/_new.html.erb
<div class="">
<% if current_user == #post.user || current_user.admin %>
<h3>Add video</h3>
<div class="">
<%= form_for [#post, #video] do |f| %>
<div class="">
<%= f.label(:title, "Video Title") %></br >
<%= f.text_field(:title) %>
</div>
<div class="">
<%= f.label(:url, "Video Url") %></br >
<%= f.text_field(:url) %>
</div>
<div class="">
<%= f.label(:tag_list, "Tags (separated by commas)") %></br >
<%= f.text_field(:tag_list, multiple: true) %>
</div>
<div class="">
<%= f.submit("Submit Video") %>
</div>
<% end %>
</div>
<% end %>
</div>
views/videos/show.html.erb
<div class="video-show">
<%= #video.title %>
<%= content_tag(:iframe, nil, src: "//www.youtube.com/embed/#{#video.embed_id}") %>
<p>
Tags: <%= #video.tag_list %>
</p>
<% if current_user == #video.user %>
<%= link_to "Edit Video", edit_video_path(#video) %> |
<%= link_to "Delete Video", video_path(#video), method: :delete, data: { confirm: "Are you sure?" } %> |
<% end %>
<% if current_user == #video.user %>
<%= link_to("Back to Log", post_path(#post)) %> |
<% end %>
<%= link_to("Back to Index", videos_path) %>
</div>
controllers/videos_controller.rb
def index
if params[:tag]
#videos = Video.tagged_with(params[:tag]).page(params[:page]).per_page(10).order(created_at: "desc")
else
#videos = Video.all.page(params[:page]).per_page(10).order(created_at: "desc")
end
end
private
def video_params
params.require(:video).permit(
:title,
:url,
:tag_list,
)
end

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

undefined method `strftime' for nil:NilClass - Comment Date

I am displaying the date when a comment is published:
<%= comment.created_at.strftime("%d %b %Y") %>
This works, except if the comment is not filled out correctly, and is submitted. If this occurs I get the error: undefined methodstrftime' for nil:NilClass` instead of my comment validations.
How to fix this, I am not sure?
Here's my code:
class CommentsController < ApplicationController
def create
#post = Post.friendly.find(params[:post_id])
#comment = #post.comments.create(params[:comment].permit(:name, `:email, :website, :body, :url))`
if #comment.errors.any?
render "posts/show"
else
redirect_to post_path(#post)
end
end
def destroy
#post = Post.friendly.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
end
class Comment < ActiveRecord::Base
belongs_to :post
validates_format_of :email, :with => /#/
validates :name, presence: true, length: { minimum: 5}
validates :body, presence: true, length: { minimum: 5}
validates :body, presence: true, length: { minimum: 5}
def gravatar_url
stripped_email = email.strip
downcased_email = stripped_email.downcase
hash = Digest::MD5.hexdigest(downcased_email)
default_url = "https://s3-us-west-2.amazonaws.com/mirror-communications/assets/download.jpg"
"http://gravatar.com/avatar/#{hash}"
end
end
<!-- Post Comments Partial -->
<li>
<article class="comment">
<div class="user-avatar">
<%= image_tag comment.gravatar_url %>
</div>
<div class="comment-content">
<h5 class="name"><%= comment.name %></h5>
<div class="comment-meta comment-reply">
<span class="post-date"><%= comment.created_at.strftime("%d %b %Y") %></span>/<span class="comment-reply-link"><%= link_to comment.website.try(:remove, /.*\/\//), url_for(comment.website), target: '_blank', class: "comment-reply" %></span>
</div>
<p><%= comment.body %></p>
</div>
</article>
<!-- Form Partial -->
<%= form_for([#post, #post.comments.build]) do |f| %>
<% if #comment && #comment.errors.any? %>
<div id="error_explanation" class="alert alert-danger alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h2><%= pluralize(#comment.errors.count, "error") %> Your comment could not be submitted:</h2>
<ul>
<% #comment.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<form class="comment-form">
<div class="row">
<div class="column width-4">
<%= f.text_field :name, class: "form-name form-element", placeholder: "Name*", :tabindex => 1 %>
</div>
<div class="column width-4">
<%= f.email_field :email, class: "form-email form-element", placeholder: "Email* (not displayed)", :tabindex => 3 %>
</div>
<div class="column width-4">
<%= f.url_field :website, class: "form-website form-element", placeholder: "Website", :tabindex => 4 %>
</div>
</div>
<div class="row">
<div class="column width-12">
<%= f.text_area :body, class: "form-message form-element", placeholder: "Message*", :tabindex => 5 %>
<%= f.submit class: "form-submit button medium bkg-black bkg-hover-turquoise color-white color-hover-white no-margin-bottom" %>
</div>
</div>
</form>
</div>
<% end %>
<!-- Posts Show -->`
<div class="post-comments">
<h3 class="comments-title">
<% if #post.comments.count < 2 %>
<%= #post.comments.count %> Comment</h3>
<% else %>
<%= #post.comments.count %> Comments</h3>
<% end %>
<div class="comments">
<ul class="comment-list">
<%= render #post.comments %>
</ul>
</div>
</div>
I think you have not populated local variable comment properly.
try this,
comment.created_at.strftime("%d %b %Y") if comment and comment.created_at

Rails 4 - Displaying a Users Search Results to a View

I'm using the Spotify API and am trying display search results for an artist on the same view page that the search form is on. I think I'm close but just need a little bit of help. Rails noob obviously..
How do I set the url http://localhost:3000/search?query=what_do_i_set_this_to??? to the user input I'm trying to collect via this line in my search form <%= text_field_tag(:query, "", class: 'form-control', autofocus: true, placeholder: "Enter artist name") %>
Much thanks in advance! I've been stuck on this for about a week now.
UPDATE (what my code currently looks like now)
Controller
artists_controller.rb
class ArtistsController < ApplicationController
def index
request = search_params[:query]
unless request.nil?
response = HTTParty.get("https://api.spotify.com/v1/search?q="+request+"&type=artist")
#hash_version = JSON.parse(response.body)
end
end
private
def search_params
params.permit(:query, :utf8, :commit)
end
end
View
artists/index.html.erb
<h1>Artist Search</h1>
<i>(search for artists you would like to follow)</i>
<br>
<br>
<%= form_tag(artists_path, method: :get) do %>
<div class="form-group">
<%= label_tag(:query, "Search artist by name:") %>
<%= text_field_tag(:query, params[:query], class: 'form-control', autofocus: true, placeholder: "Enter artist name") %>
</div>
<div class="form-group">
<%= submit_tag("Search", class: 'btn btn-success') %>
</div>
<% end %>
<% #hash_version["artists"]["items"].each_with_index do |band, index| %>
<% if index == #hash_version["artists"]["items"].size - 1 %>
<li class="artist_li">
<%= image_tag(band["images"].first["url"], class: 'img-responsive artist_img') rescue image_tag("microphone.png", class: 'img-responsive artist_img mic_bg') %>
<br>
<h1 class="artist_name"><%= band["name"] %></h1>
<br>
<% if band["genres"].empty? %>
<h5>no genres</h5>
<% else %>
<h5><%= band["genres"] %></h5>
<% end %>
<br>
<h5><%= band["followers"]["total"] %> followers</h5>
<br>
<h4>(Follow)</h4>
<!-- no hr with last li -->
</li>
<% else %>
<li class="artist_li">
<%= image_tag(band["images"].first["url"], class: 'img-responsive artist_img') rescue image_tag("microphone.png", class: 'img-responsive artist_img mic_bg') %>
<br>
<h1 class="artist_name"><%= band["name"] %></h1>
<br>
<% if band["genres"].empty? %>
<h5>no genres</h5>
<% else %>
<h5><%= band["genres"] %></h5>
<% end %>
<br>
<h5><%= band["followers"]["total"] %> followers</h5>
<br>
<h4>(Follow)</h4>
<hr class="artists_hr">
</li>
<% end %>
<% end %>
You should us the name option and passing it in the value option as params[:query] as follow :
<h1>Artist Search</h1>
<i>(search for artists you would like to follow)</i>
<br>
<br>
<%= form_tag(artists_path, method: :get) do %>
<div class="form-group">
<%= label_tag(:query, "Search artist by name:") %>
<%= text_field_tag(:query, params[:query], class: 'form-control', autofocus: true, placeholder: "Enter artist name") %>
</div>
<div class="form-group">
<%= submit_tag("Search", class: 'btn btn-success') %>
</div>
<% end %>
<% unless #hash_version.nil? %>
<% #hash_version["artists"]["items"].each_with_index do |band, index| %>
<% if index == #hash_version["artists"]["items"].size - 1 %>
<li class="artist_li">
<%= image_tag(band["images"].first["url"], class: 'img-responsive artist_img') rescue image_tag("microphone.png", class: 'img-responsive artist_img mic_bg') %>
<br>
<h1 class="artist_name"><%= band["name"] %></h1>
<br>
<% if band["genres"].empty? %>
<h5>no genres</h5>
<% else %>
<h5><%= band["genres"] %></h5>
<% end %>
<br>
<h5><%= band["followers"]["total"] %> followers</h5>
<br>
<h4>(Follow)</h4>
<!-- no hr with last li -->
</li>
<% else %>
<li class="artist_li">
<%= image_tag(band["images"].first["url"], class: 'img-responsive artist_img') rescue image_tag("microphone.png", class: 'img-responsive artist_img mic_bg') %>
<br>
<h1 class="artist_name"><%= band["name"] %></h1>
<br>
<% if band["genres"].empty? %>
<h5>no genres</h5>
<% else %>
<h5><%= band["genres"] %></h5>
<% end %>
<br>
<h5><%= band["followers"]["total"] %> followers</h5>
<br>
<h4>(Follow)</h4>
<hr class="artists_hr">
</li>
<% end %>
<% end %>
<% end %>
then in your controller just look for params[:query] and verify that it has some data before sending the request as follow :
class ArtistsController < ApplicationController
def index
request = search_params[:query]
unless request.nil?
response = HTTParty.get("https://api.spotify.com/v1/search?q="+request+"&type=artist")
#hash_version = JSON.parse(response.body)
end
end
private
def search_params
params.permit(:query, :utf8, :commit)
end
end
and you should be good :)

Resources