lazer-rails 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/README.md +35 -0
- data/Rakefile +32 -0
- data/app/assets/config/lazer_manifest.js +1 -0
- data/app/assets/stylesheets/lazer/application.css +15 -0
- data/app/controllers/lazer/application_controller.rb +22 -0
- data/app/controllers/lazer/schema_controller.rb +87 -0
- data/app/controllers/lazer/scopes_controller.rb +71 -0
- data/app/helpers/lazer/application_helper.rb +4 -0
- data/app/jobs/lazer/application_job.rb +4 -0
- data/app/mailers/lazer/application_mailer.rb +6 -0
- data/app/models/lazer/application_record.rb +5 -0
- data/app/views/layouts/lazer/application.html.erb +15 -0
- data/config/routes.rb +4 -0
- data/lib/lazer/engine.rb +5 -0
- data/lib/lazer/railtie.rb +11 -0
- data/lib/lazer/track_scopes.rb +18 -0
- data/lib/lazer/version.rb +3 -0
- data/lib/lazer.rb +5 -0
- data/lib/tasks/lazer_tasks.rake +4 -0
- metadata +90 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f69c53ae02e5623308b813b654431f012f4d582ab0d1cd4cbf9b3a4e42c910db
|
4
|
+
data.tar.gz: e43efbf348011c43c5ca09c9e7555a857c9f20254cff387bd073462ecc83b93c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 949104826f2f04efda3ba465166fb430fb83e19136b9da7f882f5bedd4ef436772963940c5bfb3e2a0631baaa4eb8d0d06166cba26f9eacd97e328af7d36196a
|
7
|
+
data.tar.gz: 77e48ac6798734dd7b094a6b796a8be1658849664cf8d0a5600710fd68e205130b1191e3b76ef547470ec9c64e0eea766a3c4dbdeb4d4c3889954f6c7444dc71
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Lazer Ruby Gem
|
2
|
+
|
3
|
+
This gem provides a Rails engine that allows Lazer to import your apps scopes and Active Record relationships.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'lazer-rails'
|
10
|
+
```
|
11
|
+
|
12
|
+
Bundle, and restart your server.
|
13
|
+
|
14
|
+
```bash
|
15
|
+
bundle
|
16
|
+
```
|
17
|
+
|
18
|
+
Mount the engine:
|
19
|
+
|
20
|
+
```
|
21
|
+
# config/routes.rb
|
22
|
+
mount Lazer::Engine => "/lazer-gem-api"
|
23
|
+
```
|
24
|
+
|
25
|
+
Add a new codebase in Lazer to get an API key, then set it as an environment variable:
|
26
|
+
|
27
|
+
```
|
28
|
+
LAZER_KEY=YOUR_API_KEY
|
29
|
+
```
|
30
|
+
|
31
|
+
## How it works
|
32
|
+
|
33
|
+
This gem adds two endpoints to your app, one for scopes and one for relationships. It uses the API key for authentication.
|
34
|
+
|
35
|
+
The Lazer app will hit these endpoints periodically so that your Lazer instance stays up to date.
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Lazer'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
task default: :test
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/lazer .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Lazer
|
2
|
+
class ApplicationController < ActionController::Base
|
3
|
+
protect_from_forgery with: :exception
|
4
|
+
|
5
|
+
before_action :authenticate!
|
6
|
+
|
7
|
+
def authenticate!
|
8
|
+
if params[:api_key].blank?
|
9
|
+
render json: "Missing api_key param", status: 401
|
10
|
+
return
|
11
|
+
end
|
12
|
+
if ENV["LAZER_KEY"].blank?
|
13
|
+
render json: "You need to set your LAZER_KEY env variable", status: 401
|
14
|
+
return
|
15
|
+
end
|
16
|
+
if params[:api_key] != ENV["LAZER_KEY"]
|
17
|
+
render json: "api_key param doesn't match LAZER_KEY env variable", status: 401
|
18
|
+
return
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require_dependency "lazer/application_controller"
|
2
|
+
|
3
|
+
module Lazer
|
4
|
+
class SchemaController < ApplicationController
|
5
|
+
|
6
|
+
def show
|
7
|
+
require_page!; return if performed?
|
8
|
+
|
9
|
+
Rails.application.eager_load!
|
10
|
+
models = ActiveRecord::Base.descendants
|
11
|
+
|
12
|
+
result = {}
|
13
|
+
|
14
|
+
page = params[:page].to_i
|
15
|
+
models_per_page = 30
|
16
|
+
offset = (page - 1) * models_per_page
|
17
|
+
|
18
|
+
models = models[offset, models_per_page] || []
|
19
|
+
result[:models] = models.map do |model|
|
20
|
+
parse_model(model)
|
21
|
+
end
|
22
|
+
|
23
|
+
# not necessarily needed, can get tables directly from the db
|
24
|
+
# result[:raw_tables] = gather_tables
|
25
|
+
|
26
|
+
result[:count] = models.length
|
27
|
+
result[:page] = page
|
28
|
+
result[:offset] = offset
|
29
|
+
|
30
|
+
render json: result.to_json
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def connection
|
36
|
+
ActiveRecord::Base.connection
|
37
|
+
end
|
38
|
+
|
39
|
+
def gather_tables
|
40
|
+
connection.tables.map do |table_name|
|
41
|
+
{ table_name =>
|
42
|
+
connection.columns(table_name).map do |column|
|
43
|
+
{
|
44
|
+
name: column.name,
|
45
|
+
type: column.type,
|
46
|
+
}
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_model(model)
|
53
|
+
logger.debug "Parsing: #{model.name}"
|
54
|
+
# return {} if model.name == "ActiveRecord::SchemaMigration"
|
55
|
+
model_data = {
|
56
|
+
name: model.name,
|
57
|
+
table: model.table_name,
|
58
|
+
}
|
59
|
+
associations = []
|
60
|
+
model.reflect_on_all_associations.each do |association|
|
61
|
+
associations << {
|
62
|
+
macro: association.macro,
|
63
|
+
name: association.name,
|
64
|
+
options: association.options,
|
65
|
+
table: association.table_name,
|
66
|
+
foreign_key: association.foreign_key,
|
67
|
+
# to_table: association.class_name.constantize.table_name,
|
68
|
+
}
|
69
|
+
end
|
70
|
+
# model_data[:columns] = model.column_names
|
71
|
+
# model_data[:scopes] = model.instance_variable_get(:@__scopes__)
|
72
|
+
model_data[:associations] = associations
|
73
|
+
return model_data
|
74
|
+
rescue => e
|
75
|
+
logger.debug "error parsing model #{model.name}: #{e.message}"
|
76
|
+
return {}
|
77
|
+
end
|
78
|
+
|
79
|
+
def require_page!
|
80
|
+
if params[:page].blank?
|
81
|
+
render json: "You must specify a page param", status: 422
|
82
|
+
return
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require_dependency "lazer/application_controller"
|
2
|
+
|
3
|
+
module Lazer
|
4
|
+
class ScopesController < ApplicationController
|
5
|
+
|
6
|
+
def show
|
7
|
+
render json: try_all_models.to_json
|
8
|
+
end
|
9
|
+
|
10
|
+
def try_all_models
|
11
|
+
Rails.application.eager_load!
|
12
|
+
models = ActiveRecord::Base.descendants
|
13
|
+
worked = []
|
14
|
+
failed = []
|
15
|
+
data = {}
|
16
|
+
|
17
|
+
models.each do |model|
|
18
|
+
begin
|
19
|
+
scopes = get_scopes_for_model(model)
|
20
|
+
if scopes.present?
|
21
|
+
data[model.name] = {
|
22
|
+
scopes: scopes,
|
23
|
+
table_name: model.table_name
|
24
|
+
}
|
25
|
+
end
|
26
|
+
worked << (model.respond_to?(:class_name) ? model.class_name : model.name)
|
27
|
+
rescue => e
|
28
|
+
failed << {
|
29
|
+
model: (model.respond_to?(:class_name) ? model.class_name : model.name),
|
30
|
+
error: e.message
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
{ success: worked, failure: failed, data: data }
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_scopes_for_model(model)
|
39
|
+
return nil unless model.respond_to?(:defined_scopes)
|
40
|
+
|
41
|
+
result = {}
|
42
|
+
all_sql = model.all.to_sql
|
43
|
+
model.defined_scopes.each do |name, block|
|
44
|
+
begin
|
45
|
+
|
46
|
+
# for each scope, check the arity. don't handle params for now
|
47
|
+
if block.respond_to?(:arity) && block.arity != 0
|
48
|
+
puts "skipped #{name} because arity was #{block.arity}"
|
49
|
+
next
|
50
|
+
end
|
51
|
+
|
52
|
+
scope_sql = model.send(name).to_sql
|
53
|
+
|
54
|
+
# return scopes that have a where or order only... skip joins for now
|
55
|
+
if !scope_sql.include?(all_sql)
|
56
|
+
puts "skipped #{name} because sql wasn't included"
|
57
|
+
next
|
58
|
+
end
|
59
|
+
|
60
|
+
new_sql = scope_sql.gsub(all_sql, "")&.strip
|
61
|
+
result[name] = new_sql
|
62
|
+
rescue => e
|
63
|
+
Rails.logger.warn "Failed processing scope #{name} on #{model.name}: #{e.message}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
result
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
data/config/routes.rb
ADDED
data/lib/lazer/engine.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Lazer
|
2
|
+
module TrackScopes
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class << self
|
7
|
+
def scope(name, options = nil, &block)
|
8
|
+
defined_scopes[name] ||= options || block
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def defined_scopes
|
13
|
+
@defined_scopes ||= {}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/lazer.rb
ADDED
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lazer-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vic Ramon
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-06-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pg
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Provides secure endpoints to export info for Lazer Pro
|
42
|
+
email:
|
43
|
+
- v@vicramon.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- app/assets/config/lazer_manifest.js
|
51
|
+
- app/assets/stylesheets/lazer/application.css
|
52
|
+
- app/controllers/lazer/application_controller.rb
|
53
|
+
- app/controllers/lazer/schema_controller.rb
|
54
|
+
- app/controllers/lazer/scopes_controller.rb
|
55
|
+
- app/helpers/lazer/application_helper.rb
|
56
|
+
- app/jobs/lazer/application_job.rb
|
57
|
+
- app/mailers/lazer/application_mailer.rb
|
58
|
+
- app/models/lazer/application_record.rb
|
59
|
+
- app/views/layouts/lazer/application.html.erb
|
60
|
+
- config/routes.rb
|
61
|
+
- lib/lazer.rb
|
62
|
+
- lib/lazer/engine.rb
|
63
|
+
- lib/lazer/railtie.rb
|
64
|
+
- lib/lazer/track_scopes.rb
|
65
|
+
- lib/lazer/version.rb
|
66
|
+
- lib/tasks/lazer_tasks.rake
|
67
|
+
homepage: https://www.github.com/vicramon/lazer-engine
|
68
|
+
licenses: []
|
69
|
+
metadata:
|
70
|
+
allowed_push_host: https://rubygems.org
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
requirements: []
|
86
|
+
rubygems_version: 3.5.3
|
87
|
+
signing_key:
|
88
|
+
specification_version: 4
|
89
|
+
summary: Provides secure endpoints to export info for Lazer Pro
|
90
|
+
test_files: []
|