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 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
@@ -0,0 +1,4 @@
1
+ module Lazer
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Lazer
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Lazer
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Lazer
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Lazer</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "lazer/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ Lazer::Engine.routes.draw do
2
+ resource :schema, controller: :schema
3
+ resource :scopes, controller: :scopes
4
+ end
@@ -0,0 +1,5 @@
1
+ module Lazer
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Lazer
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ require "rails/railtie"
2
+
3
+ module Lazer
4
+ class Railtie < ::Rails::Railtie
5
+ initializer "lazer.track_scopes" do
6
+ ActiveSupport.on_load(:active_record) do
7
+ ActiveRecord::Base.include(Lazer::TrackScopes)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -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
@@ -0,0 +1,3 @@
1
+ module Lazer
2
+ VERSION = '0.1.0'
3
+ end
data/lib/lazer.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "lazer/engine"
2
+ require "active_support"
3
+
4
+ require "lazer/track_scopes"
5
+ require "lazer/railtie" if defined?(Rails)
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :lazer do
3
+ # # Task goes here
4
+ # end
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: []