Link to Order Index Rails 4 - ruby-on-rails

I am using Rails 4 with the Impressionist gem to get view count of my Articles.
On my index page I have a link labeled "Most Popular"
I also have access to a method that will order articles by the view count:
#articles = Article.order('impressions_count ASC')
What is the best way to order the index by impression_count when a user clicks the "most popular button?" I am having trouble finding documentation on this.
Here is my articles_controller.rb
class ArticlesController < ApplicationController
load_and_authorize_resource
before_action :set_article, only: [:show, :edit, :update, :destroy]
def index
if params[:q].present?
#articles = Article.search(params[:q], misspellings: {edit_distance: 1}, page: params[:page], per_page: 12)
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
else
#articles = Article.order('impressions_count ASC').page(params[:page]).per(12)
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
end
if #articles.blank?
return redirect_to request_path
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
end
get_query
end
def autocomplete
#articles = Article.search params[:term], autocomplete: true
render json: #articles
end
def search
#articles = Article.search params[:q], suggest: true, page: params[:page], per_page: 5
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
render 'index'
end
def show
impressionist(#article, nil, { unique: [:session_hash] })
#skip_error = true
#subarticles = #article.subarticles.approved.order(:cached_votes_score => :desc)
if request.path != article_path(#article)
redirect_to #article, status: :moved_permanently
else
respond_to do |format|
format.html # show.html.erb
format.json { render json: #article }
end
end
end
def new
end
def edit
end
def create
respond_to do |format|
if #article.save
format.html { redirect_to #article, notice: 'Article was successfully created.' }
format.json { render :show, status: :created, location: #article }
else
format.html { render :new }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #article.update(article_params)
format.html { redirect_to #article, notice: 'Article was successfully updated.' }
format.json { render :show, status: :ok, location: #article }
else
format.html { render :edit }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
def destroy
#article.destroy
respond_to do |format|
format.html { redirect_to articles_url, notice: 'Article was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_article
#article = Article.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def article_params
params.require(:article).permit(:title, :specific, :category, :aka, :image1, :image2, :video1, :video2)
end
def get_query
#userquery = params[:q]
end
end

The first else clause in your index is this:
else
#articles = Article.order('impressions_count ASC').page(params[:page]).per(12)
That is why you are getting them sorted by impressions_count. Just get rid of it to return them sorted by most recent.
else
#articles = Article.order(created_at: :desc).page(params[:page]).per(12)
You then need to set your "most popular" link to return the #articles variable sorted by impressions_count as you did in your old code.
You will need to make your action in the controller to return the results you want, something like:
Add a variable to your whitelist:
def article_params
params.require(:article).permit(:title, :specific, :category, :aka, :image1, :image2, :video1, :video2, :imp_sort)
end
Then in your index action you can add it in:
def index
if params[:q].present?
#articles = Article.search(params[:q], misspellings: {edit_distance: 1}, page: params[:page], per_page: 12)
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
else
if article_params[:imp_sort]
#articles = Article.order('impressions_count ASC').page(params[:page]).per(12)
else
#articles = Article.order(created_at: :desc).page(params[:page]).per(12)
end
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
end
if #articles.blank?
return redirect_to request_path
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
end
get_query
end
in your index.html.erb you will need to have your link do something like:
<%= link_to "Sort by Impressions", articles_path(:imp_sort => true) %>

Related

undefined method `each' for nil:NilClass, how to set my instance variable?

I am trying to search by keywords some titles, I need help to set my instances variables tutos.... ( It seems that I need two instances #tutos... but I don't know how to do?
I tried:
#tutos = Tuto.all.includes(:user, :category) || Tuto.search(params[:search]) but I have the same error...
I have undefined method each' for nil:NilClass even though I have the instance variable set... thanks for your help
my controller
class TutosController < ApplicationController
before_action :authenticate_user!, only: [:new, :create]
before_action :set_tuto, only: [:show, :edit, :update, :destroy, :upvote]
def index
#tutos = Tuto.all.includes(:user, :category)
keyword_search
#categories = Category.all
end
def keyword_search
#tutos = Tuto.search(params[:search])
end
def show
#tuto = Tuto.find(params[:id])
#user = User.all
end
def new
#tuto = Tuto.new
end
def edit
end
def create
#tuto = Tuto.new(tuto_params)
#tuto.user_id = current_user.id
respond_to do |format|
if #tuto.save
flash[:success] = "Test"
format.html { redirect_to #tuto, notice: 'Tuto was successfully created.' }
format.json { render :show, status: :created, location: #tuto }
else
format.html { render :new }
format.json { render json: #tuto.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #tuto.update(tuto_params)
format.html { redirect_to #tuto, notice: 'Tuto was successfully updated.' }
format.json { render :show, status: :ok, location: #tuto }
else
format.html { render :edit }
format.json { render json: #tuto.errors, status: :unprocessable_entity }
end
end
end
def destroy
#tuto.destroy
respond_to do |format|
format.html { redirect_to tutos_url, notice: 'Tuto was successfully destroyed.' }
format.json { head :no_content }
end
end
def upvote
#tuto.upvote_by current_user
redirect_to :back
end
private
def set_tuto
#tuto = Tuto.find(params[:id])
end
def tuto_params
params.require(:tuto).permit(:title, :content, :id, :user_id, :category_id)
end
end
my index
.container
.row
.col-xs-12
h1.text-gray Tutorials
h4 Search by Title
=form_tag tutos_path, :method => 'get' do
=text_field_tag :search, params[:search]
=submit_tag "Search", class:'btn btn-default'
= form_tag '/tutos', method: 'get' do
select[name="category.id"]
- #categories.each do |category|
| <option value="
= category.id
| ">
= category.name
input[type="submit" value="Search", class="btn btn-default"]
.col-xs-12
-if user_signed_in?
= link_to "Create a tuto", new_tuto_path, class:"btn btn-success"
br
br
#tutos.transitions-enabled
-#tutos.each do |tuto|
.box.panel-default
= link_to image_tag(image_by_category(tuto.category.try(:name))), tuto_path(tuto)
h3 = link_to tuto.title, tuto_path(tuto), class:"title-link"
h6
| Created by:
span<>
= tuto.user.full_name
br
span.glyphicon.glyphicon-heart
span<>
= tuto.get_upvotes.size
br
br
tuto model
class Tuto < ActiveRecord::Base
acts_as_votable
belongs_to :user
belongs_to :category
validates :category_id, presence: true
def self.search(search)
if search
where(["title LIKE ?","%#{search}%"])
else
all
end
end
end
Update your index like this. you don't need keyword_search.
def index
if params[:search]
#tutos = Tuto.search(params[:search]).includes(:user, :category)
else
#tutos = Tuto.all.includes(:user, :category)
end
#categories = Category.all
end
Hope this helps.
def index
#tutos = Tuto.all.includes(:user, :category)
keyword_search // **Here you are overriding #tutos... First have no meaning always**
#categories = Category.all
end
def keyword_search
#tutos = Tuto.search(params[:search])
end
2 ->
def self.search(search)
if search
where(["title LIKE ?","%#{search}%"])
else
all
end
end
It will give nil if searched data is not available, so you should handle this.. otherwise each with nil occurs

Simple-Form input :collection does not highlight field when error is raised

I have a problem with simple form it doesn’t highlight field where error is raised.
search_controller.rb
class SearchesController < ApplicationController
before_action :set_search, only: [:show, :edit, :update, :destroy]
layout 'admin'
def index
#searches = Search.includes(:brand, :search_index, :price_ranges)
end
def show
end
def new
#search = Search.new
end
def edit
end
def create
#search = Search.new(search_params)
respond_to do |format|
if #search.save
format.html { redirect_to #search, notice: 'Search was successfully created.' }
format.json { render :show, status: :created, location: #search }
else
format.html { render :new }
format.json { render json: #search.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #search.update(search_params)
format.html { redirect_to searches_url, notice: 'Search was successfully updated.' }
format.json { render :show, status: :ok, location: #search }
else
format.html { render :edit }
format.json { render json: #search.errors, status: :unprocessable_entity }
end
end
end
def destroy
#search.destroy
respond_to do |format|
format.html { redirect_to searches_url, notice: 'Search was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_search
#search = Search.find(params[:id])
end
def search_params
params.require(:search).permit(:brand_id)
end
end
search.rb
class Search < ActiveRecord::Base
validates_presence_of :brand
_form.html.erb
<%= simple_form_for(#search) do |f| %>
<%= f.error_notification %>
<%= f.input :brand_id, collection: Brand.all.order(:name), prompt: 'Select brand' %>
<% end %>
I want brand field be hihlighted the same way keywords field is.
I've checked if validates_presence_of brand raise the error and it dose, but doesn’t highlight the field.

How to access variables and methods across controllers in Rails

Books Controller:
class BooksController < ApplicationController
before_action :set_book, only: [:show, :edit, :update, :destroy]
# GET /books
# GET /books.json
def index
if params[:student_id]
student = Student.find(params[:student_id])
#books = student.books
else
#books = Book.all
end
respond_to do |format|
format.html
format.csv {render text: #books.to_csv }
end
end
def show
end
def new
#book = Book.new
end
def edit
end
def create
#book = Book.new(book_params)
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'Book was successfully created.' }
format.json { render :show, status: :created, location: #book }
else
format.html { render :new }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #book.update(book_params)
format.html { redirect_to #book, notice: 'Book was successfully updated.' }
format.json { render :show, status: :ok, location: #book }
else
format.html { render :edit }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
def destroy
#book.destroy
respond_to do |format|
format.html { redirect_to books_url, notice: 'Book was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_book
#book = Book.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def book_params
params.require(:book).permit(:book_name, :book_level, :total_words, :words_wrong, :self_corrections, :student_id)
end
end
Here is my "Students Controller"
class StudentsController < ApplicationController
def show
#student = Student.find(params[:id]) rescue nil
#books = Book.where(student_id: params[:id])
#book = Book.new
end
def create
student = Student.new(student_parameters)
student.user_id = current_user.id
if student.save
redirect_to student
else
redirect_to 'students#index'
end
end
def index
#students = Student.where("user_id = ?",current_user.id)
#student = Student.new
end
private
def student_parameters
params.require(:student).permit(:first_name, :last_name)
end
end
Books belong to students, and on the index view where I show an individual's students books, I want the heading at the top of the page to say "{current student}'s book". I'm unsure as to how to call the name of the current student, and I think the source of my confusion is the fact that I'm working with the books controller and student.first_name and student.last_name aren't available to me.
Additionally, I would like to know how to access book data when I'm using the students controller. For instance when I'm at localhost:3000/students/2, I'd like to show all that students books.
I'm looking for something like current_student.books or current_student.name, I think, but I'm not sure how to create them.
Instead of doing...
student = Student.find(params[:student_id])
#books = student.books
do...
#student = Student.find(params[:student_id])
#books = #student.books
This gives you the instance variable #student that you can use in your views, in particular #student.first_name and #student.last_name
you may want to condition the code in the view so that it only shows if #student is not nil (it would be nil if params[:student_id] wasn't passed).

Ruby Error ActiveRecord::RecordNotFound

The page you were looking for doesn't exist. You may have mistyped the address or the page may have moved.
Error log:
Started GET "/ru" for 0.0.0.0 at 2014-04-08 08:03:02 +0300
Processing by PagesController#main as HTML
Parameters: {"locale"=>"ru"}
Completed 404 Not Found in 14ms
ActiveRecord::RecordNotFound (Couldn't find Page with id=4):
app/controllers/pages_controller.rb:9:in `main'
pages_controller:
class PagesController < ApplicationController
before_filter :authenticate, :only => [:index, :show, :new, :edit, :create, :update, :destroy ]
caches_page :main, :about, :showreal, :projects, :contacts, :reject
caches_action :index, :show, :new
def main
#page = case I18n.locale.to_s
when 'ru'; Page.find(4)
when 'zh'; Page.find(6)
else Page.find(2)
end
base = 'app/assets/videos/'
#video = Dir.glob(File.join(base, 'main', 'video.*')).first.sub!(base,"")
#preview = Dir.glob(File.join(base, 'main', 'preview.*')).first.sub!(base,"")
end
def about
#body_class = 'leftbg'
#page = case I18n.locale.to_s
when 'ru'; Page.find(3)
when 'zh'; Page.find(5)
else Page.find(1)
end
end
def showreal
base = 'app/assets/videos/'
#video = Dir.glob(File.join(base, 'showreal', 'video.*')).first.sub!(base,"")
#preview = Dir.glob(File.join(base, 'showreal', 'preview.*')).first.sub!(base,"")
end
def projects
end
def contacts
#body_class = 'leftbg'
end
def sent
redirect_to :action => "reject" and return unless request.post?
#body_class = 'leftbg'
if request.POST.include? 'name'
#name = request.params['name']
end
if request.POST.include? 'email'
#email = request.params['email']
end
if request.POST.include? 'phone'
#phone = request.params['phone']
end
if request.POST.include? 'message'
#message = request.params['message']
end
if ['name','email','phone','message'].all? {|i| request.POST.include?(i)}
ContactMailer.contacts_email(#name,#email,#phone,#message).deliver
else
flash[:error] = 'You must complete all fields!'
return render :action => "contacts"
end
end
def reject
#body_class = 'leftbg'
end
# GET /pages
# GET /pages.json
def index
#pages = Page.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #pages }
end
end
# GET /pages/1
# GET /pages/1.json
def show
#page = Page.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #page }
end
end
# GET /pages/new
# GET /pages/new.json
def new
#page = Page.new
expire_page :action => [:main, :about]
expire_action :action => [:index, :show]
respond_to do |format|
format.html # new.html.erb
format.json { render json: #page }
end
end
# GET /pages/1/edit
def edit
#page = Page.find(params[:id])
end
# POST /pages
# POST /pages.json
def create
#page = Page.new(params[:page])
respond_to do |format|
if #page.save
format.html { redirect_to #page, notice: 'Page was successfully created.' }
format.json { render json: #page, status: :created, location: #page }
else
format.html { render action: "new" }
format.json { render json: #page.errors, status: :unprocessable_entity }
end
end
end
# PUT /pages/1
# PUT /pages/1.json
def update
#page = Page.find(params[:id])
expire_page :action => [:main, :about]
expire_action :action => [:index, :show]
respond_to do |format|
if #page.update_attributes(params[:page])
format.html { redirect_to #page, notice: 'Page was successfully updated.' }
format.json { head :ok }
else
format.html { render action: "edit" }
format.json { render json: #page.errors, status: :unprocessable_entity }
end
end
end
# DELETE /pages/1
# DELETE /pages/1.json
def destroy
#page = Page.find(params[:id])
#page.destroy
expire_page :action => [:main, :about]
expire_action :action => [:index, :show]
respond_to do |format|
format.html { redirect_to pages_url }
format.json { head :ok }
end
end
end
What could be the problem?
Stopped all work after work of a programmer, he was doing something with the cache.
Problem is here
#page = Page.find(2)
Instead of using find, use where
#page = Page.where("id =?", 2).first
Then you can apply a check like
if #page.blank?
#do something
else
#do something else
end
Here's the update
#page = case I18n.locale.to_s
when 'ru'; Page.where("id =?", 4).first
when 'zh'; Page.where("id =?", 6).first
else Page.where("id =?", 6).first
end

Missing Template and Controller Issues in Rails Project (rating)

I am stuck on a problem and i would love a hand! I got the polymorphic association from railscast #154
So far I have gotten the comment model working splendidly. However I want to create a rating model as well that I can then add js to make pretty.
Looked at every other tutorial/stackoverflows I could find. None of them show how to work with multiple polymorphic associations in a controller.
I tried to duplicate the code for the article_controller but I am not sure how to do that for both models. So far my attempts have been unsuccessful. The partial form has the proper name, it is _ratings.html.erb
My Error:
Missing partial ratings/ratings with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in:
* "/code/jimbo/bigdog/app/views"
* "/home/user/.rvm/gems/ruby-2.0.0-p247#lulla-core/gems/kaminari-0.14.1/app/views"
* "/home/user/.rvm/gems/ruby-2.0.0-p247#lulla-core/gems/devise-3.1.1/app/views"
My Models:
class Rating
include Mongoid::Document
include Mongoid::MultiParameterAttributes
field :value, type: Integer, default: "0"
belongs_to :rateable, polymorphic: true
end
My Controllers:
class RatingsController < ApplicationController
before_filter :load_rateable
def index
#ratings = #rateable.rating
end
def show
#rating = #rateable.ratings.find(params[:id])
respond_to do |format|
format.html # show.html.erb
end
end
def new
#rating = #rateable.rating.new
end
def create
#rating = #rateable.rating.new(params[:rating])
if #rating.save
redirect_to #rateable, notice: "Rating created."
else
render :new
end
end
private
def load_rateable
resource, id = request.path.split('/')[1, 2]
#rateable = resource.singularize.classify.constantize.find(id)
end
# def load_commentable
# klass = [Article, Photo, Event].detect { |c| params["#{c.name.underscore}_id"] }
# #rateable = klass.find(params["#{klass.name.underscore}_id"])
# end
end
Article Controller
class ArticlesController < ApplicationController
# GET /articles
# GET /articles.json
def index
#articles = Article.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #articles }
end
end
# GET /articles/1
# GET /articles/1.json
def show
#article = Article.find(params[:id])
#commentable = #article
#comments = #commentable.comments
#comment = Comment.new
respond_to do |format|
format.html # show.html.erb
format.json { render json: #article }
end
end
# GET /articles/new
# GET /articles/new.json
def new
#article = Article.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #article }
end
end
# GET /articles/1/edit
def edit
#article = Article.find(params[:id])
end
# POST /articles
# POST /articles.json
def create
#article = Article.new(params[:article])
respond_to do |format|
if #article.save
format.html { redirect_to #article, notice: 'Article was successfully created.' }
format.json { render json: #article, status: :created, location: #article }
else
format.html { render action: "new" }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
# PUT /articles/1
# PUT /articles/1.json
def update
#article = Article.find(params[:id])
respond_to do |format|
if #article.update_attributes(params[:article])
format.html { redirect_to #article, notice: 'Article was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.json
def destroy
#article = Article.find(params[:id])
#article.destroy
respond_to do |format|
format.html { redirect_to articles_url }
format.json { head :no_content }
end
end
end
My View:
show.html (article)
<%= render "comments/comments" %>
<%= render "comments/form" %>
<%= render "ratings/ratings" %>
<%= render "ratings/form" %>
Routes:
resources :articles do
resources :comments
resources :ratings
end

Resources