├── .gitignore ├── LICENCE ├── MIT-LICENCE ├── README.md ├── app ├── controllers │ └── concerns │ │ └── ransack_memory │ │ └── concern.rb ├── helpers │ └── ransack_memory_helper.rb └── views │ └── shared │ ├── _ransack_memory_clear_filter.html.erb │ └── _ransack_memory_clear_filter.html.haml ├── generators └── ransack_memory │ └── ransack_memory_generator.rb ├── lib ├── generators │ └── ransack_memory_generator.rb ├── ransack_memory.rb ├── ransack_memory │ ├── engine.rb │ └── version.rb └── templates │ └── ransack_memory │ └── ransack_memory_template.rb └── ransack_memory.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.gem -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Richard Lapiš 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /MIT-LICENCE: -------------------------------------------------------------------------------- 1 | Copyright 2018 richard.lapis@gmail.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ransack Memory 2 | 3 | This Gem provides automatic saving your filtered Ransack gem params into Rails session. It also autoloads params from session to your search forms. 4 | 5 | ## Installation 6 | Add this line to your application's Gemfile: 7 | 8 | ```ruby 9 | gem 'ransack_memory' 10 | ``` 11 | 12 | Run the generator 13 | 14 | ```shell 15 | rails generate ransack_memory 16 | ``` 17 | 18 | Add this line to your basic controller (typically ApplicationController): 19 | 20 | ```ruby 21 | class ApplicationController < ActionController::Base 22 | include RansackMemory::Concern # insert this line 23 | 24 | before_action :authenticate_user! # only if you use Devise gem 25 | before_action :save_and_load_filters # insert this line after Devise auth before filter (Devise gem is not necessary) 26 | end 27 | ``` 28 | 29 | Add this in your views where you have search forms. This is clear button, which deletes ransack memory sessions. 30 | ```erb 31 | <%= clear_filter %> 32 | ``` 33 | You can pass any of link attributes: 34 | 35 | ```erb 36 | <%= clear_filter title: 'Clear Filter', class: 'btn btn-primary', data: {confirm: 'Really?', my_data: 'something'} %> 37 | ``` 38 | 39 | ## Configuration 40 | 41 | Running ```rails generate ransack_memory``` the console will generate `config/initializers/ransack_memory.rb` with this content: 42 | 43 | ```ruby 44 | RansackMemory::Core.config = { 45 | param: :q, # this means the default Ransack param name for searching. You can change it 46 | session_key_format: '%controller_name%_%action_name%_%request_format%' # this means how the key used to store the information to the session will be stored. Currently it interpolates request parameters. You can customize it and use these vars to build a key that fits your needs 47 | } 48 | ``` 49 | 50 | ## Load saved filters from another controller action 51 | 52 | In some cases, you want to load saved filters from another controller action. If so, you just create in the same controller this method: 53 | 54 | ```ruby 55 | def set_session_key_identifier 56 | 'projects_index_html' if action_name == 'my_another_action' 57 | end 58 | ``` 59 | this means that Ransack Memory load all filters that have been saved in action projects/index.html and load them into projects/my_another_action. This method must be public, not in private section! 60 | Standard session key building is: ```"#{controller_name}_#{action_name}_#{request.format}"``` so you can load saved filters in any controller action like that. 61 | 62 | ## Kaminari issue 63 | 64 | When you have an issue with Kaminari gem, that you can't go back to the first page, generate a kaminari configuration in the initializers folder 65 | and set ```config.params_on_first_page = true```. 66 | 67 | As an alternative update your kaminari view in `app/views/kaminari/_first_page.html.erb`: 68 | ```erb 69 | <%= link_to_unless current_page.first?, t('views.pagination.first').html_safe, url_for(params.merge({page: 1, cancel_filter: nil})), remote: remote, class: 'btn btn-secondary' %> 70 | ``` 71 | However beware that this will probably lead to problems in later Rails versions due to a change in the way it allows you to merge parameters. 72 | -------------------------------------------------------------------------------- /app/controllers/concerns/ransack_memory/concern.rb: -------------------------------------------------------------------------------- 1 | module RansackMemory 2 | module Concern 3 | extend ActiveSupport::Concern 4 | 5 | def save_and_load_filters 6 | user_set_key_identifier = respond_to?(:set_session_key_identifier) ? send(:set_session_key_identifier) : nil 7 | 8 | session_key_identifier = ::RansackMemory::Core.config[:session_key_format] 9 | .gsub('%controller_name%', controller_path.parameterize.underscore) 10 | .gsub('%action_name%', action_name) 11 | .gsub('%request_format%', request.format.symbol.to_s) 12 | .gsub('%turbo_frame%', request.headers['Turbo-Frame'] || 'top') 13 | 14 | session_key_base = user_set_key_identifier.presence || "ranmemory_#{session_key_identifier}" 15 | session_key_base = "ranmemory_#{session_key_base}" unless session_key_base.starts_with?('ranmemory') 16 | 17 | # permit search params 18 | params[::RansackMemory::Core.config[:param]].permit! if params[::RansackMemory::Core.config[:param]].present? && params[::RansackMemory::Core.config[:param]].respond_to?(:permit) 19 | 20 | # cancel filter if button pressed 21 | if params[:cancel_filter] == "true" 22 | session["#{session_key_base}"] = nil 23 | session["#{session_key_base}_page"] = nil 24 | session["#{session_key_base}_per_page"] = nil 25 | end 26 | 27 | # search term saving 28 | session["#{session_key_base}"] = params[::RansackMemory::Core.config[:param]].to_h if params[::RansackMemory::Core.config[:param]].present? 29 | 30 | # page number saving 31 | session["#{session_key_base}_page"] = params[:page] if params[:page].present? 32 | 33 | # per page saving 34 | session["#{session_key_base}_per_page"] = params[:per_page] if params[:per_page].present? 35 | 36 | # search term load 37 | params[::RansackMemory::Core.config[:param]] = session["#{session_key_base}"] if session["#{session_key_base}"].present? 38 | 39 | # page number load 40 | params[:page] = session["#{session_key_base}_page"].presence 41 | 42 | # per page load 43 | params[:per_page] = session["#{session_key_base}_per_page"].presence 44 | 45 | # set page number to 1 if filter has changed 46 | if (params[::RansackMemory::Core.config[:param]].present? && session[:last_q_params] != params[::RansackMemory::Core.config[:param]].permit!.to_h) || (params[:cancel_filter].present? && session["#{session_key_base}_page"] != params[:page]) 47 | params[:page] = nil 48 | session["#{session_key_base}_page"] = nil 49 | end 50 | 51 | session[:last_q_params] = params[::RansackMemory::Core.config[:param]]&.to_unsafe_h 52 | 53 | # session[:last_page] = params[:page] 54 | end 55 | 56 | # controller method, useful when you want to clear sessions when sign into another user 57 | def clear_sessions 58 | session.keys.each do |key| 59 | session.delete(key) if key =~ /ranmemory_/ 60 | end 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /app/helpers/ransack_memory_helper.rb: -------------------------------------------------------------------------------- 1 | module RansackMemoryHelper 2 | def clear_filter(opts = {}) 3 | render 'shared/ransack_memory_clear_filter', opts: opts 4 | end 5 | end -------------------------------------------------------------------------------- /app/views/shared/_ransack_memory_clear_filter.html.erb: -------------------------------------------------------------------------------- 1 | <% if params[RansackMemory::Core.config[:param].presence || :q].present? %> 2 | <%= link_to opts[:title].presence || 'Clear filter', url_for + "?cancel_filter=true", opts.except(:title) %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/shared/_ransack_memory_clear_filter.html.haml: -------------------------------------------------------------------------------- 1 | - if params[RansackMemory::Core.config[:param].presence || :q].present? 2 | = link_to opts[:title] || 'Clear filter', url_for + "?cancel_filter=true", opts.except(:title) -------------------------------------------------------------------------------- /generators/ransack_memory/ransack_memory_generator.rb: -------------------------------------------------------------------------------- 1 | class RansackMemoryGenerator < Rails::Generator::Base 2 | def manifest 3 | record do |m| 4 | m.file "ransack_memory.rb", "config/initializers/ransack_memory.rb" 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/generators/ransack_memory_generator.rb: -------------------------------------------------------------------------------- 1 | if defined?(Rails) 2 | 3 | # Rails3 generator invoked with 'rails generate ransack_memory' 4 | class RansackMemoryGenerator < Rails::Generators::Base 5 | source_root(File.expand_path(File.dirname(__FILE__) + "/../templates/ransack_memory")) 6 | def copy_initializer 7 | 8 | template 'ransack_memory_template.rb', 'config/initializers/ransack_memory.rb' 9 | end 10 | end 11 | 12 | end 13 | -------------------------------------------------------------------------------- /lib/ransack_memory.rb: -------------------------------------------------------------------------------- 1 | module RansackMemory 2 | 3 | require 'ransack_memory/version' 4 | require 'ransack_memory/engine' if defined?(::Rails) 5 | 6 | class Core 7 | @@config = {} 8 | cattr_accessor :config 9 | 10 | def initialize(opts = {}) 11 | @opts = opts 12 | end 13 | end 14 | 15 | end 16 | -------------------------------------------------------------------------------- /lib/ransack_memory/engine.rb: -------------------------------------------------------------------------------- 1 | module RansackMemory 2 | class Engine < ::Rails::Engine 3 | end 4 | end -------------------------------------------------------------------------------- /lib/ransack_memory/version.rb: -------------------------------------------------------------------------------- 1 | module RansackMemory 2 | VERSION = '0.1.0' 3 | end -------------------------------------------------------------------------------- /lib/templates/ransack_memory/ransack_memory_template.rb: -------------------------------------------------------------------------------- 1 | RansackMemory::Core.config = { 2 | # This means the default Ransack param name for searching. You can change it 3 | param: :q, 4 | 5 | # This means how the key used to store the information to the session 6 | # will be stored. Currently it interpolates request parameters. 7 | # You can customize it and use these vars to build a key that fits your needs 8 | # 9 | # Available variables are: 10 | # controller_name 11 | # action_name 12 | # request_format 13 | # turbo_frame 14 | <% if defined? Turbo -%> 15 | session_key_format: '%controller_name%_%action_name%_%request_format%_%turbo_frame%' 16 | <% else -%> 17 | session_key_format: '%controller_name%_%action_name%_%request_format%' 18 | <% end -%> 19 | } 20 | -------------------------------------------------------------------------------- /ransack_memory.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | 3 | # Maintain your gem's version: 4 | require "ransack_memory/version" 5 | 6 | Gem::Specification.new do |s| 7 | s.name = "ransack_memory" 8 | s.version = RansackMemory::VERSION 9 | s.platform = Gem::Platform::RUBY 10 | s.required_ruby_version = '>= 1.9.3' 11 | 12 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= 13 | s.authors = ["Richard Lapiš"] 14 | s.date = %q{2018-06-25} 15 | s.description = %q{Automatically save and load ransack's filtered params into session} 16 | s.email = %q{richard.lapis@gmail.com} 17 | s.files = `git ls-files`.split("\n") 18 | s.test_files = [] 19 | s.homepage = %q{https://github.com/richardrails/ransack_memory} 20 | s.files = Dir["{app,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] 21 | s.rubygems_version = %q{1.6.2} 22 | s.summary = %q{Automatically save and load ransack's filtered params into session} 23 | s.license = 'MIT' 24 | 25 | if s.respond_to? :specification_version then 26 | s.specification_version = 3 27 | 28 | if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then 29 | else 30 | end 31 | else 32 | end 33 | end --------------------------------------------------------------------------------