0

I have a Entry model that has_many courses through entry_courses (has_many through association). I've set up my scope as such in my entry.rb (model)

scope :by_courses, -> (ids_ary) {
  joins(entry_courses: :course).where("courses.id" => ids_ary)
}

Using this, I'm able to filter using a URL http://localhost:3000/entries?by_courses[]=5

This filters the proper entries with course_id = 5.

So, my question is, how can I display the active filter (course name) at the top of the index.html.erb view when that param is passed in the URL?

Model

class Entry < ApplicationRecord
    mount_uploader :attachment, AttachmentUploader

    has_many :entry_topics
    has_many :topics, through: :entry_topics

    has_many :entry_categories
    has_many :categories, through: :entry_categories

    has_many :entry_courses
    has_many :courses, through: :entry_courses



    belongs_to :user
    scope :by_categories, ->(ids_ary) { joins(entry_categories: :category).where("categories.id" => ids_ary) }
    scope :by_topics, ->(ids_ary) { joins(entry_topics: :topic).where("topics.id" => ids_ary) }
    scope :by_level, -> level { where(:level => level) }
    scope :by_courses, -> (ids_ary) { joins(entry_courses: :course).where("courses.id" => ids_ary) }

end

Controller

class EntriesController < ApplicationController
  before_action :set_entry, only: [:show, :edit, :update, :destroy]
  before_action :set_variables, only: [:new, :create, :show, :edit, :update, :index]
  before_action :authenticate_user!, only: [:new, :create, :edit, :update]
  before_action :user_is_current_user, only: [:edit, :update, :destroy]
  has_scope :by_categories, type: :array
  has_scope :by_level, type: :array
  has_scope :by_topics, type: :array
  has_scope :by_courses, type: :array


  # GET /entries
  # GET /entries.json
  def index
 @entries = if params[:term]
    Entry.where('title ILIKE ?', "%#{params[:term]}%")
  else    
    @entries = apply_scopes(Entry.order(:created_at => 'DESC'))
  end

  end



  # GET /entries/1
  # GET /entries/1.json
  def show
  end

  # GET /entries/new
  def new
    @entry = Entry.new(:user => @current_user)
  end

  # GET /entries/1/edit
  def edit

  end

  # POST /entries
  # POST /entries.json
  def create

    @entry = Entry.new(entry_params)
    @entry.user_id = current_user.id

    respond_to do |format|
      if @entry.save

        format.html { redirect_to @entry, notice: 'Entry was successfully created.' }
        format.json { render :show, status: :created, location: @entry }

      else
        format.html { render :new }
        format.json { render json: @entry.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /entries/1
  # PATCH/PUT /entries/1.json
  def update
   user = User.find_by_id(@entry.user_id)
   entry = @entry
    respond_to do |format|
      if @entry.update(entry_params)
        format.html { redirect_to @entry, notice: 'Entry was successfully updated.' }
        format.json { render :show, status: :ok, location: @entry }
      else
        format.html { render :edit }
        format.json { render json: @entry.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /entries/1
  # DELETE /entries/1.json
  def destroy
    @entry.destroy
    respond_to do |format|
      format.html { redirect_to entries_url, notice: 'Entry was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_entry
      @entry = Entry.find(params[:id])

    end
    def set_variables
      @categories = Category.all
      @topics = Topic.all
      @courses = Course.all

    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def entry_params
      params.require(:entry).permit({topic_ids: []}, {category_ids: []}, {course_ids: []}, :description, :category_id, :title, :entry_type,:entry_type_other, :genre, :level, :course,  :attachment, :remove_attachment, :entry_id, :user, :user_id, :id, :url_link, :term)
    end
    def user_is_current_user
    unless current_user == @entry.user or current_user.admin?
      redirect_to(root_url, alert: "Sorry! You can't edit this resource since you didn't create it.") and return
    end
  end
end
chris
  • 61
  • 1
  • 7

1 Answers1

1

Using current_scopes in your view will return a hash of {by_courses: 5} or similar.

how can I display the active filter (course name)

In application_helper.rb

def entries_name
  scope = current_scope.first 
  model = entries_scope_map[scope[0]]
  model.find(scope[1][0]).name
end 

def entries_scope_map
  {by_courses: Course}
end

In your view (or similar):

<%= entries_name %> 
Josh Brody
  • 5,153
  • 1
  • 14
  • 25
  • Yes! That worked. However, is there any way I can display the name attribute instead of {:by_courses=>["5"]} – chris Jul 29 '18 at 01:43
  • `current_scopes.keys.first` – Josh Brody Jul 29 '18 at 01:52
  • Hmm...that didn't work. It's just displaying by_courses now. – chris Jul 29 '18 at 01:54
  • Oops I misunderstood your question. See my edit for what I would do :) – Josh Brody Jul 29 '18 at 01:58
  • Thanks for your help so far, man! I've tried your solution above and it's still not working (just displaying "Course Name" and nothing else). To clarify, each course has an id (obviously) and a field called :name. Passing current_scopes successfully displays the ID (so I know the scope is working!), but I can't get the corresponding :name field to display instead of the ID. – chris Jul 29 '18 at 02:05
  • It's not the most ideal, but `@entries.first.course.name` would be one way to do it. – Josh Brody Jul 29 '18 at 02:12
  • Sorry to keep pestering! @entries.first.course.name gives a nil class error. undefined method `name' for nil:NilClass – chris Jul 29 '18 at 02:15
  • Try `@entries.first.entry_courses.first.course.name` — without seeing more of your model and controller code I'm merely taking potshots here. – Josh Brody Jul 29 '18 at 02:17
  • Thanks man, I've added my model and controller to the original post. The last suggestion didn't work. It just displayed the first Course, not the current scoped course. – chris Jul 29 '18 at 02:24
  • There's probably a million better ways to do it that are more safe, but I updated my answer to reflect what is a poor attempt. – Josh Brody Jul 29 '18 at 02:30
  • Thanks again. Still no luck. Getting this error: undefined method `[]' for nil:NilClass on the model line. No biggie. Thank you for your help. – chris Jul 29 '18 at 02:36
  • It works when a scope is applied! The only problem is that when there is no scope it throws the undefined method `[]' for nil:NilClass error. – chris Jul 29 '18 at 02:49
  • you should check to see if a scope is applied then. – Josh Brody Jul 29 '18 at 04:26