avo 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of avo might be problematic. Click here for more details.

Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +49 -48
  3. data/Gemfile.lock +19 -2
  4. data/README.md +33 -54
  5. data/app/controllers/avo/application_controller.rb +34 -1
  6. data/app/controllers/avo/filters_controller.rb +19 -0
  7. data/app/controllers/avo/relations_controller.rb +34 -0
  8. data/app/controllers/avo/resource_overview_controller.rb +14 -7
  9. data/app/controllers/avo/resources_controller.rb +66 -142
  10. data/app/controllers/avo/search_controller.rb +55 -0
  11. data/app/helpers/avo/application_helper.rb +6 -2
  12. data/app/views/layouts/avo/_javascript.html.erb +1 -0
  13. data/app/views/layouts/avo/application.html.erb +34 -17
  14. data/app/views/partials/_footer.html.erb +1 -1
  15. data/app/views/partials/_header.html.erb +1 -1
  16. data/avo.gemspec +18 -4
  17. data/config/credentials.yml.enc +1 -0
  18. data/config/routes.rb +11 -7
  19. data/lib/avo.rb +2 -0
  20. data/lib/avo/app/app.rb +18 -29
  21. data/lib/avo/app/authorization_service.rb +40 -0
  22. data/lib/avo/app/fields/has_and_belongs_to_many.rb +1 -0
  23. data/lib/avo/app/fields/has_many.rb +1 -0
  24. data/lib/avo/app/fields/id_field.rb +4 -4
  25. data/lib/avo/app/licensing/community_license.rb +4 -0
  26. data/lib/avo/app/licensing/hq.rb +85 -0
  27. data/lib/avo/app/licensing/license.rb +48 -0
  28. data/lib/avo/app/licensing/license_manager.rb +25 -0
  29. data/lib/avo/app/licensing/null_license.rb +12 -0
  30. data/lib/avo/app/licensing/pro_license.rb +9 -0
  31. data/lib/avo/app/resource.rb +31 -12
  32. data/lib/avo/configuration.rb +14 -0
  33. data/lib/avo/engine.rb +1 -1
  34. data/lib/avo/version.rb +1 -1
  35. data/lib/generators/avo/templates/initializer.rb +2 -0
  36. data/lib/generators/avo/templates/views/_footer.html.erb +1 -1
  37. data/lib/generators/avo/templates/views/_header.html.erb +1 -1
  38. data/lib/generators/avo/templates/views/_scripts.html.erb +0 -0
  39. data/public/avo-packs/css/application-73e568bc.css +3 -0
  40. data/public/avo-packs/css/application-73e568bc.css.br +0 -0
  41. data/public/avo-packs/css/application-73e568bc.css.gz +0 -0
  42. data/public/avo-packs/js/application-044386b1f6fe7a8dcb9f.js +3 -0
  43. data/public/avo-packs/js/{application-8071f9a0f167bb82b39d.js.LICENSE.txt → application-044386b1f6fe7a8dcb9f.js.LICENSE.txt} +0 -0
  44. data/public/avo-packs/js/application-044386b1f6fe7a8dcb9f.js.br +0 -0
  45. data/public/avo-packs/js/application-044386b1f6fe7a8dcb9f.js.gz +0 -0
  46. data/public/avo-packs/js/application-044386b1f6fe7a8dcb9f.js.map +1 -0
  47. data/public/avo-packs/js/application-044386b1f6fe7a8dcb9f.js.map.br +0 -0
  48. data/public/avo-packs/js/application-044386b1f6fe7a8dcb9f.js.map.gz +0 -0
  49. data/public/avo-packs/manifest.json +8 -6
  50. data/public/avo-packs/manifest.json.br +0 -0
  51. data/public/avo-packs/manifest.json.gz +0 -0
  52. data/public/avo-packs/media/svgs/arrow-circle-right-1ad1e15ec9a7aa54b67d126566a5aa2d.svg +1 -0
  53. data/public/avo-packs/media/svgs/arrow-circle-right-1ad1e15ec9a7aa54b67d126566a5aa2d.svg.br +0 -0
  54. data/public/avo-packs/media/svgs/arrow-circle-right-1ad1e15ec9a7aa54b67d126566a5aa2d.svg.gz +0 -0
  55. data/public/avo-packs/media/svgs/exclamation-8d1c0baa390a8df9bb52176011eb5892.svg +1 -0
  56. data/public/avo-packs/media/svgs/exclamation-8d1c0baa390a8df9bb52176011eb5892.svg.br +0 -0
  57. data/public/avo-packs/media/svgs/exclamation-8d1c0baa390a8df9bb52176011eb5892.svg.gz +0 -0
  58. metadata +70 -25
  59. data/public/avo-packs/css/application-64b0f124.css +0 -3
  60. data/public/avo-packs/css/application-64b0f124.css.br +0 -0
  61. data/public/avo-packs/css/application-64b0f124.css.gz +0 -0
  62. data/public/avo-packs/js/application-8071f9a0f167bb82b39d.js +0 -3
  63. data/public/avo-packs/js/application-8071f9a0f167bb82b39d.js.br +0 -0
  64. data/public/avo-packs/js/application-8071f9a0f167bb82b39d.js.gz +0 -0
  65. data/public/avo-packs/js/application-8071f9a0f167bb82b39d.js.map +0 -1
  66. data/public/avo-packs/js/application-8071f9a0f167bb82b39d.js.map.br +0 -0
  67. data/public/avo-packs/js/application-8071f9a0f167bb82b39d.js.map.gz +0 -0
@@ -1 +1 @@
1
- <%= link_to Avo.configuration.app_name, main_app.root_path, class: 'text-green-600 font-semibold', target: :_blank %>
1
+ <%= link_to Avo.configuration.app_name, '/', class: 'text-green-600 font-semibold', target: :_blank %>
@@ -8,22 +8,36 @@ Gem::Specification.new do |spec|
8
8
  spec.name = 'avo'
9
9
  spec.version = Avo::VERSION
10
10
  spec.authors = ['Adrian Marin', 'Mihai Marin']
11
- spec.email = ['adrian@avohq.io']
11
+ spec.email = ['avo@avohq.io']
12
12
  spec.homepage = 'https://avohq.io'
13
- spec.summary = 'Configuration based, no-maintenance, extendable Ruby on Rails admin.'
13
+ spec.summary = 'Configuration-based, no-maintenance, extendable Ruby on Rails admin.'
14
14
  spec.description = 'Avo is a beautiful next-generation framework that empowers you, the developer, to create fantastic admin panels for your Ruby on Rails apps with the flexibility to fit your needs as you grow.'
15
- spec.license = 'MIT'
15
+ spec.license = 'Commercial'
16
16
 
17
17
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
18
  # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/avo-hq/avo/issues'
21
+ spec.metadata['changelog_uri'] = 'https://avohq.io/releases'
22
+ spec.metadata['documentation_uri'] = 'https://docs.avohq.io'
23
+ spec.metadata['homepage_uri'] = 'https://avohq.io'
24
+ spec.metadata['source_code_uri'] = 'https://github.com/avo-hq/avo'
25
+ else
26
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
27
+ 'public gem pushes.'
28
+ end
29
+
30
+ spec.post_install_message = "Thank you for using Avo! Docs are available at https://docs.avohq.io"
19
31
 
20
32
  spec.files = Dir['{bin,app,config,db,lib,public}/**/*', 'MIT-LICENSE', 'Rakefile', 'README.md', 'avo.gemspec', 'Gemfile', 'Gemfile.lock']
21
33
  .reject { |file| file.start_with? 'app/frontend' }
22
34
 
23
- spec.add_dependency 'rails', '~> 6.0.2', '>= 6.0.2.1'
35
+ spec.add_dependency 'rails', '>= 6.0'
24
36
  spec.add_dependency 'kaminari'
25
37
  spec.add_dependency 'zeitwerk'
26
38
  spec.add_dependency 'inline_svg'
27
39
  spec.add_dependency 'webpacker'
28
40
  spec.add_dependency 'countries'
41
+ spec.add_dependency 'pundit'
42
+ spec.add_dependency 'httparty'
29
43
  end
@@ -0,0 +1 @@
1
+ u5m9Je6F3j/LCnOwcN7cXW37M63Bs0KNZC1fHRObWx4YQkV9DJl1k9H9+mlvV3irAC7NZB9H0BExhxquReVe2N0v6s3E3EvOWY8wfZhFONJpK8V0qerYJIhJvCOOPv0hfS/HQdcvUQx/i1faXEgr8QVR7nGVBHUzulwgab0lUBSAV0jjEbT6o+amTojFudelgtw0zmlZW9JL7OZ/IwZ7zxbi8/yoWB52lU4VKOxZV7AEWAVDzL/0ZogLRG12BsTSmqC0jS5ocdnOgV0X7oNeYL9HINqLLM5suBB+BOf3xL6vgngu7UDRAAQ/mN2TDGsvklF8bwVz0dDVQ0RuvdeQ9TWEeM75hhzGKG6wPKBjh4ebrKp7g9TT76F6omLe/hG30MbohGxaLVHIJjyJixfKlLlYwdNWeOjXwYsn--7CEWrUIlraWa8R0S--ia1zVj/2AXISMmbinw6S7g==
@@ -1,20 +1,24 @@
1
1
  Avo::Engine.routes.draw do
2
2
  root 'home#index'
3
3
 
4
- get '/avo-api/search', to: 'resources#search'
5
- get '/avo-api/:resource_name/search', to: 'resources#search'
6
- get '/avo-api/:resource_name', to: 'resources#index'
7
- get '/avo-api/:resource_name/filters', to: 'resources#filters'
4
+ get '/avo-api/:resource_name/filters', to: 'filters#index'
5
+
8
6
  get '/avo-api/:resource_name/actions', to: 'actions#index'
9
7
  post '/avo-api/:resource_name/actions', to: 'actions#handle'
8
+
9
+ get '/avo-api/search', to: 'search#index'
10
+ get '/avo-api/:resource_name/search', to: 'search#resource'
11
+
12
+ get '/avo-api/:resource_name', to: 'resources#index'
10
13
  post '/avo-api/:resource_name', to: 'resources#create'
11
- get '/avo-api/:resource_name/fields', to: 'resources#fields'
14
+ get '/avo-api/:resource_name/new', to: 'resources#new'
12
15
  get '/avo-api/:resource_name/:id', to: 'resources#show'
13
16
  get '/avo-api/:resource_name/:id/edit', to: 'resources#edit'
14
17
  put '/avo-api/:resource_name/:id', to: 'resources#update'
15
18
  delete '/avo-api/:resource_name/:id', to: 'resources#destroy'
16
- post '/avo-api/:resource_name/:id/attach/:attachment_name/:attachment_id', to: 'resources#attach'
17
- post '/avo-api/:resource_name/:id/detach/:attachment_name/:attachment_id', to: 'resources#detach'
19
+
20
+ post '/avo-api/:resource_name/:id/attach/:attachment_name/:attachment_id', to: 'relations#attach'
21
+ post '/avo-api/:resource_name/:id/detach/:attachment_name/:attachment_id', to: 'relations#detach'
18
22
 
19
23
  # Tools
20
24
  get '/avo-tools/resource-overview', to: 'resource_overview#index'
data/lib/avo.rb CHANGED
@@ -11,6 +11,8 @@ require_relative 'avo/app/filters/select_filter'
11
11
 
12
12
  require_relative 'avo/app/resource'
13
13
 
14
+ require_relative 'avo/app/licensing/license_manager'
15
+
14
16
  module Avo
15
17
  ROOT_PATH = Pathname.new(File.join(__dir__, '..'))
16
18
 
@@ -4,37 +4,35 @@ require_relative 'filters/select_filter'
4
4
  require_relative 'filters/boolean_filter'
5
5
  require_relative 'resource'
6
6
  require_relative 'tool'
7
+ require_relative 'authorization_service'
7
8
 
8
9
  module Avo
9
10
  class App
10
11
  @@app = {
11
12
  root_path: '',
12
- tools: [],
13
- tool_classes: [],
14
13
  resources: [],
15
14
  field_names: {},
16
15
  }
16
+ @@license = nil
17
17
 
18
18
  class << self
19
- def init
19
+ def boot
20
20
  @@app[:root_path] = Pathname.new(File.join(__dir__, '..', '..'))
21
- # get_tools
22
- # init_tools
23
21
  init_fields
22
+ end
23
+
24
+ def init(current_request = nil)
24
25
  init_resources
26
+ @@license = LicenseManager.new(HQ.new(current_request).response).license
25
27
  end
26
28
 
27
29
  def app
28
30
  @@app
29
31
  end
30
32
 
31
- # def tools
32
- # @@app[:tools]
33
- # end
34
-
35
- # def get_tools
36
- # @@app[:tool_classes] = ToolsManager.get_tools
37
- # end
33
+ def license
34
+ @@license
35
+ end
38
36
 
39
37
  # This method will take all fields available in the Avo::Fields namespace and create a method for them.
40
38
  #
@@ -129,23 +127,14 @@ module Avo
129
127
  name.to_s.camelize.singularize
130
128
  end
131
129
 
132
- # def init_tools
133
- # @@app[:tool_classes].each do |tool_class|
134
- # @@app[:tools].push tool_class.new
135
- # end
136
- # end
137
-
138
- # def render_navigation
139
- # navigation = []
140
- # @@app[:tools].each do |tool|
141
- # navigation.push(tool.render_navigation) if tool.class.method_defined?(:render_navigation)
142
- # end
143
-
144
- # navigation.join('')
145
- # end
146
-
147
- def get_resources_navigation
148
- App.get_resources.map { |resource| { label: resource.resource_name_plural.humanize, resource_name: resource.url.pluralize } }.to_json.to_s.html_safe
130
+ def get_resources_navigation(user)
131
+ App.get_resources
132
+ .select { |resource| AuthorizationService::authorize user, resource.model, Avo.configuration.authorization_methods.stringify_keys['index'] }
133
+ .map { |resource| { label: resource.resource_name_plural.humanize, resource_name: resource.url.pluralize } }
134
+ .reject { |i| i.blank? }
135
+ .to_json
136
+ .to_s
137
+ .html_safe
149
138
  end
150
139
  end
151
140
  end
@@ -0,0 +1,40 @@
1
+ module Avo
2
+ class AuthorizationService
3
+ class << self
4
+ def authorize(user, record, action)
5
+ return true if skip_authorization
6
+
7
+ begin
8
+ if Pundit.policy user, record
9
+ Pundit.authorize user, record, action
10
+ end
11
+ true
12
+ rescue Pundit::NotAuthorizedError => error
13
+ false
14
+ end
15
+ end
16
+
17
+ def authorize_action(user, record, action)
18
+ action = Avo.configuration.authorization_methods.stringify_keys[action.to_s]
19
+
20
+ return true if action.nil?
21
+
22
+ authorize user, record, action
23
+ end
24
+
25
+ def with_policy(user, model)
26
+ return model if skip_authorization
27
+
28
+ begin
29
+ Pundit.policy_scope! user, model
30
+ rescue => exception
31
+ model
32
+ end
33
+ end
34
+
35
+ def skip_authorization
36
+ Avo::App.license.lacks :authorization
37
+ end
38
+ end
39
+ end
40
+ end
@@ -27,6 +27,7 @@ module Avo
27
27
  fields[:relation_class] = target_resource.class.to_s
28
28
  fields[:path] = target_resource.url
29
29
  fields[:relationship] = :has_and_belongs_to_many
30
+ fields[:relationship_model] = target_resource.model.name
30
31
 
31
32
  fields
32
33
  end
@@ -27,6 +27,7 @@ module Avo
27
27
  fields[:relation_class] = target_resource.class.to_s
28
28
  fields[:path] = target_resource.url
29
29
  fields[:relationship] = :has_many
30
+ fields[:relationship_model] = target_resource.model.name
30
31
 
31
32
  fields
32
33
  end
@@ -1,14 +1,14 @@
1
1
  module Avo
2
2
  module Fields
3
3
  class IdField < Field
4
- DEFAULT_VALUE = 'id'
5
-
6
4
  def initialize(name, **args, &block)
5
+ default_value = 'id'
6
+
7
7
  if name.nil?
8
- @name = name = DEFAULT_VALUE
8
+ @name = name = default_value
9
9
  elsif !name.is_a? String and !name.is_a? Symbol
10
10
  args_copy = name
11
- @name = name = DEFAULT_VALUE
11
+ @name = name = default_value
12
12
  args = args_copy
13
13
  end
14
14
 
@@ -0,0 +1,4 @@
1
+ module Avo
2
+ class CommunityLicense < License
3
+ end
4
+ end
@@ -0,0 +1,85 @@
1
+ module Avo
2
+ class HQ
3
+ attr_accessor :current_request
4
+
5
+ ENDPOINT = 'https://avohq.io/api/v1/licenses/check'
6
+ CACHE_KEY = 'avo.hq.response'
7
+ REQUEST_TIMEOUT = 5 # seconds
8
+
9
+ def initialize(current_request)
10
+ @current_request = current_request
11
+ end
12
+
13
+ def response
14
+ @hq_response or request
15
+ end
16
+
17
+ private
18
+ def request
19
+ return cached_response if has_cached_response
20
+
21
+ begin
22
+ perform_and_cache_request
23
+ rescue HTTParty::Error => exception
24
+ cache_and_return_error 'HTTP client error.', exception.message
25
+ rescue Net::OpenTimeout => exception
26
+ cache_and_return_error 'Request timeout.', exception.message
27
+ rescue SocketError => exception
28
+ cache_and_return_error 'Connection error.', exception.message
29
+ end
30
+ end
31
+
32
+ def perform_and_cache_request
33
+ hq_response = perform_request
34
+
35
+ return cache_and_return_error 'Avo HQ Internal server error.', hq_response.body if hq_response.code == 500
36
+
37
+ cache_response 1.hour.to_i, hq_response.parsed_response if hq_response.code == 200
38
+ end
39
+
40
+ def cache_response(time, response)
41
+ response.merge!(
42
+ expiry: time,
43
+ **payload,
44
+ ).stringify_keys!
45
+
46
+ Rails.cache.write(CACHE_KEY, response, expires_in: time)
47
+
48
+ @hq_response = response
49
+
50
+ response
51
+ end
52
+
53
+ def perform_request
54
+ puts 'Performing request to avohq.io API to check license availability.'.inspect if Rails.env.development?
55
+
56
+ HTTParty.post ENDPOINT, body: payload.to_json, headers: { 'Content-type': 'application/json' }, timeout: REQUEST_TIMEOUT
57
+ end
58
+
59
+ def payload
60
+ {
61
+ license: Avo.configuration.license,
62
+ license_key: Avo.configuration.license_key,
63
+ avo_version: Avo::VERSION,
64
+ rails_version: Rails::VERSION::STRING,
65
+ ruby_version: RUBY_VERSION,
66
+ environment: Rails.env,
67
+ ip: current_request.ip,
68
+ host: current_request.host,
69
+ port: current_request.port,
70
+ }
71
+ end
72
+
73
+ def cache_and_return_error(error, exception_message = '')
74
+ cache_response 5.minutes.to_i, { error: error, exception_message: exception_message }.stringify_keys
75
+ end
76
+
77
+ def has_cached_response
78
+ Rails.cache.exist? CACHE_KEY
79
+ end
80
+
81
+ def cached_response
82
+ Rails.cache.read CACHE_KEY
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,48 @@
1
+ module Avo
2
+ class License
3
+ attr_accessor :id
4
+ attr_accessor :response
5
+ attr_accessor :valid
6
+
7
+ def initialize(response)
8
+ @response = response
9
+ @id = response['id']
10
+ @valid = response['valid']
11
+ end
12
+
13
+ def valid?
14
+ valid
15
+ end
16
+
17
+ def invalid?
18
+ !valid?
19
+ end
20
+
21
+ def pro?
22
+ id == 'pro'
23
+ end
24
+
25
+ def error
26
+ @response['error']
27
+ end
28
+
29
+ def properties
30
+ @response.slice 'valid', 'id', 'error'
31
+ end
32
+
33
+ def abilities
34
+ []
35
+ end
36
+
37
+ def can(ability)
38
+ abilities.include? ability
39
+ end
40
+
41
+ def cant(ability)
42
+ !can ability
43
+ end
44
+
45
+ alias_method :has, :can
46
+ alias_method :lacks, :cant
47
+ end
48
+ end
@@ -0,0 +1,25 @@
1
+ require_relative 'license'
2
+ require_relative 'community_license'
3
+ require_relative 'pro_license'
4
+ require_relative 'null_license'
5
+
6
+ module Avo
7
+ class LicenseManager
8
+ def initialize(hq_response)
9
+ @hq_response = hq_response
10
+ end
11
+
12
+ def license
13
+ return NullLicense.new if Rails.env.test? and ENV['RUN_WITH_NULL_LICENSE'] == '1'
14
+
15
+ case @hq_response['id']
16
+ when 'community'
17
+ CommunityLicense.new @hq_response
18
+ when 'pro'
19
+ ProLicense.new @hq_response
20
+ else
21
+ NullLicense.new @hq_response
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ module Avo
2
+ class NullLicense < License
3
+ def initialize(response = nil)
4
+ response ||= {
5
+ id: 'community',
6
+ valid: true,
7
+ }
8
+
9
+ super(response)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ module Avo
2
+ class ProLicense < License
3
+ def abilities
4
+ [
5
+ :authorization,
6
+ ]
7
+ end
8
+ end
9
+ end
@@ -12,11 +12,12 @@ module Avo
12
12
  attr_reader :default_view_type
13
13
 
14
14
  class << self
15
- def hydrate_resource(model, resource, view = :index)
15
+ def hydrate_resource(model:, resource:, view: :index, user:)
16
16
  default_panel_name = "#{resource.name} details"
17
17
 
18
18
  resource_with_fields = {
19
19
  id: model.id,
20
+ authorization: get_authorization(user, model),
20
21
  resource_name_singular: resource.resource_name_singular,
21
22
  resource_name_plural: resource.resource_name_plural,
22
23
  title: model[resource.title],
@@ -39,6 +40,8 @@ module Avo
39
40
 
40
41
  furnished_field = field.fetch_for_resource(model, resource, view)
41
42
 
43
+ next unless field_resource_authorized field, furnished_field, user
44
+
42
45
  next if furnished_field.blank?
43
46
 
44
47
  furnished_field[:panel_name] = default_panel_name
@@ -74,6 +77,22 @@ module Avo
74
77
 
75
78
  "/resources/#{url}"
76
79
  end
80
+
81
+ def get_authorization(user, model)
82
+ [:create, :update, :show, :destroy].map do |action|
83
+ [action, AuthorizationService::authorize_action(user, model, action)]
84
+ end.to_h
85
+ end
86
+
87
+ def field_resource_authorized(field, furnished_field, user)
88
+ if [Avo::Fields::HasManyField, Avo::Fields::HasAndBelongsToManyField].include? field.class
89
+ return true if furnished_field[:relationship_model].nil?
90
+
91
+ AuthorizationService.authorize user, furnished_field[:relationship_model].safe_constantize, Avo.configuration.authorization_methods.stringify_keys['index']
92
+ else
93
+ true
94
+ end
95
+ end
77
96
  end
78
97
 
79
98
  def name
@@ -138,26 +157,26 @@ module Avo
138
157
  @search
139
158
  end
140
159
 
141
- def query_search(query: '', via_resource_name: , via_resource_id:)
142
- db_query = self.model
160
+ def query_search(query: '', via_resource_name: , via_resource_id:, user:)
161
+ model_class = self.model
162
+
163
+ db_query = AuthorizationService.with_policy(user, model_class)
143
164
 
144
165
  if via_resource_name.present?
145
- related_resource = App.get_resource_by_name(via_resource_name)
146
- related_model = related_resource.model
166
+ related_model = App.get_resource_by_name(via_resource_name).model
167
+
147
168
  db_query = related_model.find(via_resource_id).public_send(self.resource_name_plural.downcase)
148
169
  end
149
170
 
171
+ new_query = []
172
+
150
173
  [self.search].flatten.each_with_index do |search_by, index|
151
- query_string = "text(#{search_by}) ILIKE '%#{query}%'"
174
+ new_query.push 'or' if index != 0
152
175
 
153
- if index == 0
154
- db_query = db_query.where query_string
155
- else
156
- db_query = db_query.or(self.model.where query_string)
157
- end
176
+ new_query.push "text(#{search_by}) ILIKE '%#{query}%'"
158
177
  end
159
178
 
160
- db_query.select("#{:id}, #{title} as \"name\"")
179
+ db_query.where(new_query.join(' '))
161
180
  end
162
181
 
163
182
  def model