filch 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +303 -0
- data/Rakefile +10 -0
- data/app/controllers/filch_controller.rb +13 -0
- data/app/views/filch/_associations.html.haml +25 -0
- data/app/views/filch/_attributes.html.haml +30 -0
- data/app/views/filch/_distinct.html.haml +4 -0
- data/app/views/filch/_eq.html.haml +7 -0
- data/app/views/filch/_form.html.haml +26 -0
- data/app/views/filch/_group.html.haml +4 -0
- data/app/views/filch/_gt.html.haml +2 -0
- data/app/views/filch/_limit.html.haml +5 -0
- data/app/views/filch/_lt.html.haml +2 -0
- data/app/views/filch/_null.html.haml +5 -0
- data/app/views/filch/_options.html.haml +11 -0
- data/app/views/filch/_order.html.haml +4 -0
- data/app/views/filch/_pg_group.html.haml +6 -0
- data/app/views/filch/_pluck.html.haml +4 -0
- data/app/views/filch/_quick.html.haml +3 -0
- data/app/views/filch/_scopes.html.haml +11 -0
- data/app/views/filch/_search.html.haml +12 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config/initializers/assets.rb +1 -0
- data/config/initializers/ransack.rb +100 -0
- data/config/routes.rb +3 -0
- data/filch.gemspec +40 -0
- data/lib/filch.rb +375 -0
- data/lib/filch/datalist.rb +26 -0
- data/lib/filch/engine.rb +5 -0
- data/lib/filch/error.rb +4 -0
- data/lib/filch/model_find.rb +17 -0
- data/lib/filch/ransack_plus.rb +34 -0
- data/lib/filch/version.rb +3 -0
- data/vendor/assets/javascripts/filch.js +1 -0
- data/vendor/assets/javascripts/filchColClick.js +6 -0
- data/vendor/assets/javascripts/filchDataList.js +21 -0
- data/vendor/assets/javascripts/unhideForm.js +19 -0
- metadata +202 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
# The filch controller.
|
2
|
+
class FilchController < ::ApplicationController
|
3
|
+
# Datalist returns data for the datalist.
|
4
|
+
def datalist
|
5
|
+
model, column, pq = params[:column].split('.')
|
6
|
+
ransack_q = Filch.datalist(model, column, params[pq])
|
7
|
+
render(
|
8
|
+
partial: 'filch/quick',
|
9
|
+
layout: false,
|
10
|
+
locals: { q: ransack_q }
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
-template_config.associations_keys.each do |assoc|
|
2
|
+
-template_config.associations[assoc].each do |attr, preds|
|
3
|
+
-model_name = model.name
|
4
|
+
-id = "#{template}_#{model_name}_#{assoc}_#{attr}"
|
5
|
+
- datalist_id = "#{id}_datalist"
|
6
|
+
-assoc_attrs = {shId: "#{id}_column", datalist: datalist_id, id: id + '_head'}.merge(html_attrs[:assocs])
|
7
|
+
%p.js{assoc_attrs}
|
8
|
+
="#{assoc} #{attr}"
|
9
|
+
%table{id: "#{id}_column", class: attr}
|
10
|
+
%tr
|
11
|
+
%td
|
12
|
+
|
13
|
+
-datalist_attrs = {id: datalist_id, updateInner_addvars: "#{model_name}.#{attr}.#{f.options[:as]}"}.merge(html_attrs[:datalist])
|
14
|
+
%datalist{datalist_attrs}
|
15
|
+
%option
|
16
|
+
|
17
|
+
-preds.each do |pred|
|
18
|
+
%tr{class: pred}
|
19
|
+
-if lookup_context.find_all("filch/_#{pred}").any?
|
20
|
+
=render("filch/#{pred}", f: f, datalist_id: datalist_id, attr: "#{assoc}_#{attr}", model: model, html_attrs: html_attrs)
|
21
|
+
-else
|
22
|
+
%td.label{html_attrs[:label]}=pred
|
23
|
+
%td.no_partial
|
24
|
+
-field_hash = {list: datalist_id, placeholder:"#{attr} #{pred}"}.merge(html_attrs[:field])
|
25
|
+
=f.text_field("#{assoc}_#{attr}_#{pred}", field_hash)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
-template_config.attributes_keys.each do |attr|
|
2
|
+
-model_name = model.name
|
3
|
+
-id = "#{template}_#{model_name}_#{attr}"
|
4
|
+
-datalist_id = "#{id}_datalist"
|
5
|
+
-attrs_attrs = {shId: "#{id}_column", datalist: datalist_id, id: id + '_head'}.merge(html_attrs[:attrs])
|
6
|
+
%p.js{attrs_attrs}
|
7
|
+
=attr
|
8
|
+
%table.js{id: "#{id}_column", class: attr}
|
9
|
+
%tr
|
10
|
+
%td
|
11
|
+
-# TODO: have results from before
|
12
|
+
-# load options now?
|
13
|
+
-# TODO: why not load all datalists at the same time!
|
14
|
+
-datalist_attrs = {id: datalist_id, updateInner_addvars: "#{model_name}.#{attr}.#{f.options[:as]}"}.merge(html_attrs[:datalist])
|
15
|
+
%datalist{datalist_attrs}
|
16
|
+
%option
|
17
|
+
|
18
|
+
-template_config.attributes[attr].each do |pred|
|
19
|
+
%tr{class: pred}
|
20
|
+
-if lookup_context.find_all("filch/_#{attr}_#{pred}").any?
|
21
|
+
=render("filch/#{attr}_#{pred}", f: f, datalist_id: datalist_id, attr: attr, pred: pred, model: model, default_value: template_config.default_values["#{attr}_#{pred}"] || '', html_attrs: html_attrs)
|
22
|
+
-elsif lookup_context.find_all("filch/_#{pred}").any?
|
23
|
+
=render("filch/#{pred}", f: f, datalist_id: datalist_id, attr: attr, model: model, default_value: template_config.default_values["#{attr}_#{pred}"] || '', html_attrs: html_attrs)
|
24
|
+
-else
|
25
|
+
%td{html_attrs[:label]}
|
26
|
+
= pred
|
27
|
+
%td.no_partial
|
28
|
+
-field_hash = {list: datalist_id, placeholder:"#{attr} #{pred}"}.merge(html_attrs[:field])
|
29
|
+
-field_hash[:value]= template_config.default_values["#{attr}_#{pred}"]
|
30
|
+
=f.text_field("#{attr}_#{pred}", field_hash)
|
@@ -0,0 +1,7 @@
|
|
1
|
+
%td.label{html_attrs[:label]} equals
|
2
|
+
%td
|
3
|
+
-# dont update datalist with _eq
|
4
|
+
- default_value ||= ''
|
5
|
+
- field_hash = {list: datalist_id, class: 'form-control', placeholder: "#{attr} equals"}
|
6
|
+
- field_hash[:value] = default_value
|
7
|
+
=f.search_field("#{attr}_eq", html_attrs[:field].merge(field_hash))
|
@@ -0,0 +1,26 @@
|
|
1
|
+
-sattrs_class = "#{template} js"
|
2
|
+
-sattrs={id: "#{model.name}_#{template}_form", class: sattrs_class, method: :post}.merge(html_attrs[:search_form])
|
3
|
+
=search_form_for @q, url: results_p, html: sattrs do |f|
|
4
|
+
%p.btn.btn-sm.js{click: 'clearAll' }
|
5
|
+
Clear All
|
6
|
+
%table{id: model.name + '_table'}
|
7
|
+
%tr
|
8
|
+
%td.attributes
|
9
|
+
=render('filch/attributes', model: model, f: f, template: template, template_config: template_config, html_attrs: html_attrs)
|
10
|
+
%tr
|
11
|
+
%td.associations
|
12
|
+
=render('filch/associations', model: model, f: f, template: template, template_config: template_config, html_attrs: html_attrs)
|
13
|
+
%tr
|
14
|
+
%td.scopes
|
15
|
+
%h4
|
16
|
+
=render('filch/scopes', model: model, f: f, template: template, template_config: template_config)
|
17
|
+
%tr
|
18
|
+
%td.options
|
19
|
+
=render('filch/options', model: model, template_config: template_config)
|
20
|
+
%tr
|
21
|
+
%td
|
22
|
+
=hidden_field_tag 'template', template
|
23
|
+
=hidden_field_tag 'model', model
|
24
|
+
- fattrs = {class: 'js submit',
|
25
|
+
attr: 'action', elem: 'word_search', attr_val: '/search'}
|
26
|
+
=f.submit("search", fattrs)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
%table
|
2
|
+
-template_config.options.each do |option|
|
3
|
+
%tr{class: option}
|
4
|
+
-if lookup_context.find_all("filch/_#{option}").any?
|
5
|
+
=render("filch/#{option}", f: f, option: option, model: model, default_value: template_config.default_values[option] || [])
|
6
|
+
-else
|
7
|
+
%td
|
8
|
+
=option
|
9
|
+
%td.nopartial
|
10
|
+
=check_box_tag("o[#{option}]", 1, template_config.default_values[option] || false)
|
11
|
+
|
@@ -0,0 +1,6 @@
|
|
1
|
+
%td
|
2
|
+
group for:
|
3
|
+
%td
|
4
|
+
-default_value ||= []
|
5
|
+
=f.collection_check_boxes(:pg_group, model.columns, :name, :name, {include_hidden: false}) do |box|
|
6
|
+
= box.label {default_value.include?(box.value) ? box.check_box( checked: true ) + box.text : box.check_box(checked: false) + box.text}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
%table
|
2
|
+
-template_config.scopes.each do |scope_name|
|
3
|
+
%tr{class: scope_name}
|
4
|
+
-if lookup_context.find_all("filch/_#{scope_name}").any?
|
5
|
+
=render("filch/#{scope_name}", f: f, model: model, scope_name: scope_name, default_value: template_config.default_values[scope_name] || nil)
|
6
|
+
-else
|
7
|
+
%td
|
8
|
+
=scope_name
|
9
|
+
%td.nopartial
|
10
|
+
=check_box_tag("q[#{scope_name}", 1, template_config.default_values[scope_name] || false)
|
11
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
= javascript_include_tag 'js_weber'
|
2
|
+
= javascript_include_tag 'filch'
|
3
|
+
-button_attrs= filch.html_attrs[:button]
|
4
|
+
%button#filch_button.js.btn.btn-sm.collapsed{button_attrs}
|
5
|
+
=button_name
|
6
|
+
%span#filch
|
7
|
+
-select_h = {class: 'js', change: 'showSelected', load: 'showSelected'}
|
8
|
+
-t_keys = filch.template_keys
|
9
|
+
-if t_keys.length > 1
|
10
|
+
=select_tag 'template', options_for_select(t_keys, params[:template]), select_h
|
11
|
+
-t_keys.each do |template|
|
12
|
+
=render('filch/form', model: filch.model, template: template, template_config: filch.templates[template], results_p: results_p, html_attrs: filch.html_attrs)
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'filch'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Rails.application.config.assets.precompile += %w[filch.js]
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# all this was necessary to give me a case sensitive predicate!!!
|
2
|
+
# stolen from https://github.com/activerecord-hackery/ransack/issues/699
|
3
|
+
# {{
|
4
|
+
Ransack.configure do |config|
|
5
|
+
config.add_predicate(
|
6
|
+
'like',
|
7
|
+
arel_predicate: 's_matches',
|
8
|
+
formatter: proc { |v| "%#{v}%" },
|
9
|
+
type: :string
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
module Arel
|
14
|
+
module Nodes
|
15
|
+
# creates an arel predicate for case sensitive searching in postgres
|
16
|
+
class Matches < Binary
|
17
|
+
attr_reader :escape
|
18
|
+
attr_accessor :case_sensitive
|
19
|
+
|
20
|
+
def initialize(left, right, escape = nil, case_sensitive = false)
|
21
|
+
super(left, right)
|
22
|
+
@escape = escape && Nodes.build_quoted(escape)
|
23
|
+
@case_sensitive = case_sensitive
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# DoesNotMatch will inherit from matches
|
28
|
+
class DoesNotMatch < Matches; end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module Arel
|
33
|
+
# adding s_metches to Arel::Predications
|
34
|
+
module Predications
|
35
|
+
# creates an arel predicate for case sensitive searching in postgres
|
36
|
+
def s_matches(other, escape = nil)
|
37
|
+
Nodes::Matches.new self, quoted_node(other), escape, true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module Arel
|
43
|
+
module Visitors
|
44
|
+
# changes postgres query to casesensitive
|
45
|
+
class PostgreSQL < Arel::Visitors::ToSql
|
46
|
+
private
|
47
|
+
|
48
|
+
# arel doesnt use snakecase??
|
49
|
+
def visit_Arel_Nodes_Matches(oth, col)
|
50
|
+
col = infix_value oth, col, oth.case_sensitive ? ' LIKE ' : ' ILIKE '
|
51
|
+
escape = oth.escape
|
52
|
+
return col unless escape
|
53
|
+
visit escape, col << ' ESCAPE '
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
# }}
|
59
|
+
|
60
|
+
# Array Contains
|
61
|
+
# {{{
|
62
|
+
# https://github.com/activerecord-hackery/ransack/issues/321
|
63
|
+
module Arel
|
64
|
+
# create arel predicate for array
|
65
|
+
module Predications
|
66
|
+
def array_cont(other)
|
67
|
+
Nodes::Equality.new(
|
68
|
+
Nodes.build_quoted(other, self), Nodes::NamedFunction.new('ANY', [self])
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
Ransack.configure do |config|
|
75
|
+
config.add_predicate :array_cont, arel_predicate: :array_cont
|
76
|
+
end
|
77
|
+
# }}}
|
78
|
+
|
79
|
+
# Array Not Contains
|
80
|
+
# {{{
|
81
|
+
# https://github.com/activerecord-hackery/ransack/issues/321
|
82
|
+
module Arel
|
83
|
+
# create arel predicate for not array not contains
|
84
|
+
module Predications
|
85
|
+
def array_not_cont(other)
|
86
|
+
Nodes::DoesNotMatch.new(
|
87
|
+
Nodes.build_quoted(other, self),
|
88
|
+
Nodes::NamedFunction.new('ALL', [self])
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
Ransack.configure do |config|
|
95
|
+
config.add_predicate :array_not_cont, arel_predicate: :array_not_cont
|
96
|
+
end
|
97
|
+
# }}}
|
98
|
+
|
99
|
+
#
|
100
|
+
# vim:foldmethod=marker
|
data/config/routes.rb
ADDED
data/filch.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'filch/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'filch'
|
7
|
+
spec.version = Filch::VERSION
|
8
|
+
spec.authors = ['ynweber']
|
9
|
+
spec.email = ['foo']
|
10
|
+
|
11
|
+
spec.summary = %(a search form builder.)
|
12
|
+
spec.description = %(Creates search forms based on templates configurable in
|
13
|
+
model. Using Ransack.)
|
14
|
+
spec.homepage = 'https://bitbucket.org/ynweber/filch/'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
18
|
+
spec.metadata['source_code_uri'] = 'https://bitbucket.org/ynweber/filch/src'
|
19
|
+
spec.metadata['changelog_uri'] = 'https://bitbucket.org/ynweber/filch/commits/'
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been
|
23
|
+
# added into git.
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
25
|
+
`git ls-files -z`.split("\x0")
|
26
|
+
.reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
|
+
end
|
28
|
+
spec.bindir = 'exe'
|
29
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ['lib']
|
31
|
+
|
32
|
+
spec.add_dependency 'haml'
|
33
|
+
spec.add_dependency 'js_weber'
|
34
|
+
spec.add_dependency 'ransack'
|
35
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
36
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
37
|
+
spec.add_development_dependency 'minitest-rails'
|
38
|
+
spec.add_development_dependency 'minitest-reporters', '>= 1.1'
|
39
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
40
|
+
end
|
data/lib/filch.rb
ADDED
@@ -0,0 +1,375 @@
|
|
1
|
+
require 'filch/version'
|
2
|
+
require 'filch/engine'
|
3
|
+
require 'filch/error'
|
4
|
+
require 'filch/datalist'
|
5
|
+
require 'filch/ransack_plus'
|
6
|
+
require 'filch/model_find'
|
7
|
+
|
8
|
+
# = The Filch Gem
|
9
|
+
# the Filch Gem is entirely based on the
|
10
|
+
# ransack[https://github.com/activerecord-hackery/ransack] gem
|
11
|
+
# Filch allows for easy advanced form building.
|
12
|
+
#
|
13
|
+
# ==Features
|
14
|
+
# Filch::Templates:: The Filch::Templates object is used when generating
|
15
|
+
# the form(s).
|
16
|
+
# Filch::Datalist:: Text fields are linked to a <datalist>.
|
17
|
+
# Uses javascript to update the list with
|
18
|
+
# Filch::Datalist.quick
|
19
|
+
# Filch::RansackPlus:: Certain methods I couldn't do with Ransack/Arel.
|
20
|
+
module Filch
|
21
|
+
def self.templates(model)
|
22
|
+
Templates.new(model)
|
23
|
+
end
|
24
|
+
|
25
|
+
# calls the Filch::Datalist.quick method.
|
26
|
+
# <i>model_name</i> is a String representing the name of the model.
|
27
|
+
# <i>attr</i> is a String representing the attribute to query.
|
28
|
+
# <i>params</i> is the form's params.
|
29
|
+
#
|
30
|
+
# returns an Array 'plucked' from the results
|
31
|
+
#
|
32
|
+
# this method is usually called internally, from javascript
|
33
|
+
def self.datalist(model_name, attr, params)
|
34
|
+
Datalist.quick(model(model_name), attr, params)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Filch::RansackPlus.
|
38
|
+
# recieves the form <i>params<i>, for the 'plus' methods
|
39
|
+
# <i>q</i> is the form object.
|
40
|
+
# returns an array of ransacked results
|
41
|
+
def self.ransack_plus(params, query)
|
42
|
+
RansackPlus.new(params, query)
|
43
|
+
end
|
44
|
+
|
45
|
+
# model_find should be a String representing the name of a model.
|
46
|
+
# returns a model.
|
47
|
+
# If model_find is nil, or the model is not found, return the first model.
|
48
|
+
def self.model(model_find = nil)
|
49
|
+
ModelFind.find(model_find)
|
50
|
+
end
|
51
|
+
|
52
|
+
# = Templates
|
53
|
+
# Builds a hash. keys ares are an array template_keys
|
54
|
+
# , values are Filch::Template.
|
55
|
+
# @templates[template_key] = Filch::Template.new(@model, template_key)
|
56
|
+
# template_keys can be defined in the model
|
57
|
+
# class Foo < ApplicationRecord
|
58
|
+
# def self.filch_template_keys
|
59
|
+
# %i[all basic]
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
class Templates
|
63
|
+
def initialize(model)
|
64
|
+
@model = model
|
65
|
+
@templates = build_templates
|
66
|
+
end
|
67
|
+
attr_reader :templates, :model
|
68
|
+
|
69
|
+
def html_attrs_values
|
70
|
+
{
|
71
|
+
assocs: { click: 'filchColClick', load: 'toggleShowHide' },
|
72
|
+
attrs: { click: 'filchColClick', load: 'toggleShowHide' },
|
73
|
+
button: {
|
74
|
+
click: 'toggleShowHide', shId: 'filch', load: 'toggleShowHide'
|
75
|
+
},
|
76
|
+
datalist: {
|
77
|
+
updateInner_path: '/filch/datalist', class: 'js', update: 'dlUpdate'
|
78
|
+
},
|
79
|
+
field: { class: 'js form-control', input: 'filchDataList' },
|
80
|
+
label: { class: 'cheese'}
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def model_html_attrs
|
85
|
+
model_attrs = if @model.methods.include?(:filch_html_attrs)
|
86
|
+
@model.filch_html_attrs
|
87
|
+
else
|
88
|
+
{}
|
89
|
+
end
|
90
|
+
model_attrs.default = {}
|
91
|
+
model_attrs
|
92
|
+
end
|
93
|
+
|
94
|
+
def html_attrs
|
95
|
+
attrs = html_attrs_values
|
96
|
+
attrs.default = {}
|
97
|
+
attrs.each_key do |key|
|
98
|
+
attrs[key] = attrs[key].merge(model_html_attrs[key])
|
99
|
+
end
|
100
|
+
attrs
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
# def button_attrs
|
105
|
+
# attrs = {
|
106
|
+
# }
|
107
|
+
# if @model.methods.include?(:button_attrs)
|
108
|
+
# attrs = attrs.merge(@model.button_attrs) || attrs
|
109
|
+
# end
|
110
|
+
# attrs
|
111
|
+
# end
|
112
|
+
|
113
|
+
def build_templates
|
114
|
+
templates = {}
|
115
|
+
templates.default = Template.new(@model, 'default')
|
116
|
+
template_keys.each do |template|
|
117
|
+
templates[template] = Template.new(@model, template)
|
118
|
+
end
|
119
|
+
templates
|
120
|
+
end
|
121
|
+
|
122
|
+
# will generate forms based on the list of templates in the Array
|
123
|
+
# <i>YourModel.template_keys</i>.
|
124
|
+
# defaults to ['all']
|
125
|
+
def template_keys
|
126
|
+
if @model.methods.include?(:template_keys)
|
127
|
+
@model.template_keys || ['all']
|
128
|
+
else
|
129
|
+
['all']
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# The Template Object
|
135
|
+
# defines a template
|
136
|
+
# recieves a model Object, and a String representing the name of the template.
|
137
|
+
# returns a new object with the following attributes:
|
138
|
+
# [associations_keys] an Array of Strings representing the names of the
|
139
|
+
# the Filch::Associations to be queryed.
|
140
|
+
# [associations] a Hash of Strings representing the predicates to be queryed.
|
141
|
+
# [attribute_keys] same as association_keys, for the the Filch::Attributes
|
142
|
+
# [attributes] same as associations, for the Filch::Attributes.
|
143
|
+
# [scope_keys] same as association_keys, for the Filch::Scopes
|
144
|
+
# [scopes] same as associations, for the Filch::Scopes
|
145
|
+
class Template
|
146
|
+
def initialize(model, template)
|
147
|
+
@model = model
|
148
|
+
@template = template
|
149
|
+
@assocs = Associations.new(model)
|
150
|
+
@attrs = Attributes.new(model)
|
151
|
+
end
|
152
|
+
attr_reader :model
|
153
|
+
|
154
|
+
def attributes
|
155
|
+
@attrs.attributes[@template]
|
156
|
+
end
|
157
|
+
|
158
|
+
def attributes_keys
|
159
|
+
@attrs.attributes_keys[@template]
|
160
|
+
end
|
161
|
+
|
162
|
+
def associations
|
163
|
+
@assocs.associations[@template]
|
164
|
+
end
|
165
|
+
|
166
|
+
def associations_keys
|
167
|
+
@assocs.associations_keys[@template]
|
168
|
+
end
|
169
|
+
|
170
|
+
def df_vals
|
171
|
+
{}
|
172
|
+
end
|
173
|
+
|
174
|
+
def default_values
|
175
|
+
if @model.methods.include?(:filch_defaults)
|
176
|
+
df_vals.merge(@model.filch_defaults[@template])
|
177
|
+
else
|
178
|
+
df_vals
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def options
|
183
|
+
if @model.methods.include?(:filch_options)
|
184
|
+
@model.filch_options[@template] || {}
|
185
|
+
else
|
186
|
+
{}
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def scopes
|
191
|
+
Scopes.new(@model).scopes[@template]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# associations_keys, to determine which associations to query &
|
196
|
+
# #associations, to determine which predicates to query on those associations.
|
197
|
+
class Associations
|
198
|
+
def initialize(model)
|
199
|
+
@model = model
|
200
|
+
@ransackable_associations = @model ? @model.ransackable_associations : []
|
201
|
+
end
|
202
|
+
|
203
|
+
# the associated models to be queryed.
|
204
|
+
# associations_keys can be defined in the model
|
205
|
+
# class Foo < ApplicationRecord
|
206
|
+
# has_many :employees
|
207
|
+
# has_many :pay_stubs
|
208
|
+
# def self.filch_assoc_keys
|
209
|
+
# %i[employess pay_stubs]
|
210
|
+
# end
|
211
|
+
# end
|
212
|
+
#
|
213
|
+
# defaults to all ransackable_associtations
|
214
|
+
def associations_keys
|
215
|
+
assoc_keys =
|
216
|
+
if @model.methods.include?(:filch_assoc_keys)
|
217
|
+
@model.filch_assoc_keys
|
218
|
+
else
|
219
|
+
{}
|
220
|
+
end
|
221
|
+
assoc_keys.default = @ransackable_associations
|
222
|
+
assoc_keys[:all] = @ransackable_associations
|
223
|
+
assoc_keys
|
224
|
+
end
|
225
|
+
|
226
|
+
# a hash representing all the predicates to be queryed for a given
|
227
|
+
# association.
|
228
|
+
# #associations can be defined in the model
|
229
|
+
# class Foo < ApplicationRecord
|
230
|
+
# has_many :employees
|
231
|
+
# has_many :pay_stubs
|
232
|
+
# def self.filch_associations
|
233
|
+
# {
|
234
|
+
# basic_template: {
|
235
|
+
# employee: {
|
236
|
+
# name: %w[eq cont]
|
237
|
+
# },
|
238
|
+
# pay_stub: {
|
239
|
+
# year: %w[eq gt]
|
240
|
+
# }
|
241
|
+
# }
|
242
|
+
# }
|
243
|
+
# end
|
244
|
+
# end
|
245
|
+
#
|
246
|
+
# defaults to all ransackable_attributes for a given association with a
|
247
|
+
# value of ['eq']
|
248
|
+
def associations
|
249
|
+
assoc_hash =
|
250
|
+
if @model.methods.include?(:filch_associations)
|
251
|
+
@model.filch_associations
|
252
|
+
else
|
253
|
+
{}
|
254
|
+
end
|
255
|
+
assoc_hash.default = all
|
256
|
+
assoc_hash[:all] = all
|
257
|
+
assoc_hash
|
258
|
+
end
|
259
|
+
|
260
|
+
# TODO: specialize defaults to class types
|
261
|
+
# using class_eval(assoc.capitalize).columns
|
262
|
+
# doesnt work if belongs_to is not the same name as class
|
263
|
+
def all
|
264
|
+
@ransackable_associations.each_with_object({}) do |assoc, all_hash|
|
265
|
+
all_hash[assoc] = Hash.new(['eq'])
|
266
|
+
next unless Object.const_defined?(assoc.capitalize)
|
267
|
+
all_hash_assoc(all_hash, assoc)
|
268
|
+
# assoc_class_name = assoc.capitalize
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def all_hash_assoc(all_hash, assoc)
|
273
|
+
Object.const_get(assoc.capitalize).ransackable_attributes
|
274
|
+
.each { |attr| all_hash[assoc][attr] = ['eq'] }
|
275
|
+
all_hash
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# similar to Filch::Associations, except doesn't use predicates, and
|
280
|
+
# ransackable_scopes <b>must be</b> defined.
|
281
|
+
# class Foo < ApplicationRecord
|
282
|
+
# scope :managers, -> { where(position: 'Manager') }
|
283
|
+
# scope :store_managers, -> { where(position: 'StoreManager') }
|
284
|
+
# def self.ransackable_scopes
|
285
|
+
# %w[managers, store_managers]
|
286
|
+
# end
|
287
|
+
# end
|
288
|
+
#
|
289
|
+
# defaults to <i>ransackable_scopes</i>
|
290
|
+
class Scopes
|
291
|
+
def initialize(model)
|
292
|
+
@model = model
|
293
|
+
end
|
294
|
+
|
295
|
+
# can be defined on the model
|
296
|
+
# class Foo < ApplicationRecord
|
297
|
+
# def self.filch_scopes
|
298
|
+
# %w[managers, store_managers]
|
299
|
+
def scopes
|
300
|
+
scopes_hash = Hash.new(default)
|
301
|
+
if @model.methods.include?(:filch_scopes)
|
302
|
+
scopes_hash = scopes_hash.merge(@model.filch_scopes)
|
303
|
+
end
|
304
|
+
scopes_hash[:all] = @model ? @model.ransackable_scopes : []
|
305
|
+
scopes_hash
|
306
|
+
end
|
307
|
+
|
308
|
+
def default
|
309
|
+
default_hash = {}
|
310
|
+
default_hash
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
# similar to Filch::Associations
|
315
|
+
class Attributes
|
316
|
+
def initialize(model)
|
317
|
+
@model = model
|
318
|
+
@ransackable_attributes = @model ? @model.ransackable_attributes : []
|
319
|
+
end
|
320
|
+
|
321
|
+
# defaults to <i>Foo.ransackable_attributes</i>
|
322
|
+
def attributes_keys
|
323
|
+
attributes_keys =
|
324
|
+
@model.methods.include?(:filch_attrs) ? @model.filch_attrs : {}
|
325
|
+
attributes_keys.default = @ransackable_attributes
|
326
|
+
attributes_keys[:all] = @ransackable_attributes
|
327
|
+
attributes_keys
|
328
|
+
end
|
329
|
+
|
330
|
+
def attributes
|
331
|
+
attributes_hash = Hash.new(default)
|
332
|
+
if @model.methods.include?(:filch_attributes)
|
333
|
+
# attributes_hash.merge(@model.filch_attributes)
|
334
|
+
attributes_hash = attributes_hash.merge(@model.filch_attributes)
|
335
|
+
end
|
336
|
+
# attributes_hash = default_values(attributes_hash)
|
337
|
+
attributes_hash.each_value { |template_h| template_h.default = ['eq'] }
|
338
|
+
attributes_hash
|
339
|
+
end
|
340
|
+
|
341
|
+
def all
|
342
|
+
all_hash = {}
|
343
|
+
@ransackable_attributes.each do |attr|
|
344
|
+
all_hash[attr] = types[attr_columns(attr)]
|
345
|
+
end
|
346
|
+
all_hash
|
347
|
+
end
|
348
|
+
|
349
|
+
def attr_columns(attr)
|
350
|
+
@model.columns.select { |col| col.name == attr }.first.type
|
351
|
+
end
|
352
|
+
|
353
|
+
def default
|
354
|
+
def_hash = Hash.new(['eq'])
|
355
|
+
def_hash[:all] = all
|
356
|
+
def_hash
|
357
|
+
end
|
358
|
+
|
359
|
+
# TODO: setup defaults based on column_type
|
360
|
+
def types
|
361
|
+
{
|
362
|
+
integer: %w[eq lt gt],
|
363
|
+
string: %w[null eq start matches],
|
364
|
+
text: types_hash['string'],
|
365
|
+
boolean: %w[null]
|
366
|
+
}
|
367
|
+
end
|
368
|
+
|
369
|
+
def types_hash
|
370
|
+
{
|
371
|
+
string: ['eq']
|
372
|
+
}
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|