Trailblazer generating a loading error only when a "step Macro" is used - trailblazer

I'm running into a loading issue with my Trailblazer-Rails app. I can solve the loading issue using require, but, based on trailblazer-loader's readme, it doesn't seem like I should need to use `require.
My app has a file structure like so
app
-|concepts
---|email_address
-----|person
-------|operation
---------|test.rb
-----|schema
-------|create.rb
My understanding is that app > concepts > email_address > schema > create.rb should be loaded before app > concepts > email_address > person > operation > test.rb, based on the nesting level and the fact that operations are loaded last.
So far, referencing email_address > schema > create.rb from within a method of email_address > person > operation > test.rb hasn't caused any issues.
I've decided to DRY up my code however, and add a step Macro which references email_address > schema > create.rb and that is causing autoloading problems (specifically, app/concepts/email_address/schema/create.rb:2:in '<class:EmailAddress>': Schema is not a class (TypeError)).
I can fix this error by either using require to specify loading, or by moving email_address > person > operation > test.rb inside email_address > schema > new_folder > test.rb (in which case loading works normally without needing a require).
Any ideas on why my use of a step Macro is changing the order things need to be loaded in? I'm trying to understand what's going on.
Here's the relevant code:
module Macro
def self.ValidateParams(schema:)
step = ->(input, options) {
unless input[:validate] == false
options['contract.default'] = schema.(input['params'])
options[:params] = options['contract.default'].output
options['contract.default'].success? && input['current_user']
else
options[:params] = params
end
}
[ step, name: "validate_params.#{schema.name}" ]
end
end
class ApplicationSchema < Dry::Validation::Schema
configure do |config|
config.messages_file = './config/dry_messages.yml'
config.type_specs = true
end
def self.schema
Dry::Validation.Form(self)
end
def self.call(params)
self.schema.call(params)
end
end
class EmailAddress
class Schema
class Create < ApplicationSchema
define! do
required(:email_address, Types::Email).value(:str?)
optional(:email_label, Types::String).maybe(:str?)
optional(:email_primary, Types::Bool).value(:bool?)
end
end
end
end
class Test < Trailblazer::Operation
step Macro::ValidateParams(schema: EmailAddress::Schema::Create)
step :do_everything!
def do_everything!(options, params:, **)
p "Successfully validated params! Score!"
end
end
The code above causes problems. Below, where I reference EmailAddress::Schema::Create within Test but not within a step Macro, there aren't any loading problems:
class Test < Trailblazer::Operation
step :do_everything!
def do_everything!(options, params:, **)
EmailAddress::Person::Schema::Create.(params) # <-- works fine
p "Successfully validated params! Score!"
end
end
I don't know of any reason why a step Macro would change the required loading order of my app. Any suggestions are greatly appreciated!!

Related

How to use CustomHealthCheck with health_check gem in ruby?

From the health_check official site, we know that it can add a config.add_custom_check block in the config file:
https://github.com/ianheggie/health_check
# Add one or more custom checks that return a blank string if ok, or an error message if there is an error
config.add_custom_check do
CustomHealthCheck.perform_check # any code that returns blank on success and non blank string upon failure
end
# Add another custom check with a name, so you can call just specific custom checks. This can also be run using
# the standard 'custom' check.
# You can define multiple tests under the same name - they will be run one after the other.
config.add_custom_check('sometest') do
CustomHealthCheck.perform_another_check # any code that returns blank on success and non blank string upon failure
end
But about the CustomHealthCheck class, how to define it?
For okcomputer gem, it offers a way like this:
https://github.com/sportngin/okcomputer
# config/initializers/okcomputer.rb
class MyCustomCheck < OkComputer::Check
def check
if rand(10).even?
mark_message "Even is great!"
else
mark_failure
mark_message "We don't like odd numbers"
end
end
end
OkComputer::Registry.register "check_for_odds", MyCustomCheck.new
Didn't find the usage about health_check gem.
Update
I have tried:
Add these source in the config/initializers/health_check.rb file:
class CustomHealthCheck
def perform_check
if rand(10).even?
p "Even is great!"
else
p "We don't like odd numbers"
end
end
end
HealthCheck.setup do |config|
...
Run curl -v localhost:3000/health_check.json, got:
{"healthy":false,"message":"health_check failed: undefined method `perform_check' for CustomHealthCheck:Class"}%
Update 2
Edited source in config/initializers/health_check.rb:
class CustomHealthCheck
def self.perform_check
p 'OK'
end
end
HealthCheck.setup do |config|
...
Got:
{"healthy":false,"message":"health_check failed: OK"}%
Success is defined by returning an empty or blank string. Right now your perform_check always returns the string "OK" which will be seen as failure.
Try this to get a passing health check:
class CustomHealthCheck
def self.perform_check
everything_is_good = true # or call some method to do more elaborate checking
return everything_is_good ? "" : "We've got Problems"
end
end

Rails set(wait: 2.minutes) method for active job does not works

Creating an background job with the resque_scheduler gem on Redis server.
class Estamps::OrderAssignment < ActiveRecord::Base
after_save :enqueue_check_status
def enqueue_check_status
AutoRejectionJob.set(wait: 2.minutes).perform_later(self.id)
end
end
class AutoRejectionJob < ActiveJob::Base
queue_as :default
def perform(*args)
order_assignment_id = args[0]
order_assignment = Estamps::OrderAssignment.find(order_assignment_id)
if order_assignment.status_id == 1 || order_assignment.status_id == nil
order_assignment.status_id = 3
order_assignment.save!
end
end
end
On creation of OrderAssignment record or when updated after 2 minutes it should run AutoRejection Job. Here the prob is the set(wait: 2.minutes) does not seem to run, i.e.
AutoRejectionJob.perform_later(self.id)
works perfectly fine, but
AutoRejectionJob.set(wait: 2.minutes).perform_later(self.id)
does nothing. Haven't been able to rectify the issue. Newbie to Rails so please help.
I see no problem with your code.
I checked : .set(wait: 2.minutes) works as expected in rails 5.0.2 on top of ruby 2.4.0
So does your call of the job.
The way I see it, you're trying to set a status used elsewhere.
Probably, the error is due to the OrderAssignment being manipulated in an outside treatment (destroyed ?)
Since you said you're new to rails (I suppose that's what "newbie" means) I'm going to make some suggestions. Disregard them if you're past that ...
There also are some great debugging tools out there to help you find what's going on : byebug, better_errors, pry and of course, the rails console.
Do yourself a favor : try them.
When I can't find my way around some behavior that goes beyond my grasp, I use some "puts", and some "try / catch errors" structures (begin rescue ensure in ruby)... :
def perform(*args)
puts "####### JOB TRIGGERED ######"
begin
order_assignment_id = args[0]
order_assignment = Estamps::OrderAssignment.find(order_assignment_id)
puts "#{order_assignment.inspect}"
if order_assignment.status_id == 1 || order_assignment.status_id == nil
order_assignment.status_id = 3
order_assignment.save!
end
puts "####### JOB DONE ######"
rescue StandardError => e
# ... display e.message ...
ensure
#...
end
end
check your rails version.
check your rails logs ( log folder, all the jobs will write message to log files when performed )

Spree error when using decorator with the original code

Need a little help over here :-)
I'm trying to extend the Order class using a decorator, but I get an error back, even when I use the exactly same code from source. For example:
order_decorator.rb (the method is exactly like the source, I'm just using a decorator)
Spree::Order.class_eval do
def update_from_params(params, permitted_params, request_env = {})
success = false
#updating_params = params
run_callbacks :updating_from_params do
attributes = #updating_params[:order] ? #updating_params[:order].permit(permitted_params).delete_if { |k,v| v.nil? } : {}
# Set existing card after setting permitted parameters because
# rails would slice parameters containg ruby objects, apparently
existing_card_id = #updating_params[:order] ? #updating_params[:order][:existing_card] : nil
if existing_card_id.present?
credit_card = CreditCard.find existing_card_id
if credit_card.user_id != self.user_id || credit_card.user_id.blank?
raise Core::GatewayError.new Spree.t(:invalid_credit_card)
end
credit_card.verification_value = params[:cvc_confirm] if params[:cvc_confirm].present?
attributes[:payments_attributes].first[:source] = credit_card
attributes[:payments_attributes].first[:payment_method_id] = credit_card.payment_method_id
attributes[:payments_attributes].first.delete :source_attributes
end
if attributes[:payments_attributes]
attributes[:payments_attributes].first[:request_env] = request_env
end
success = self.update_attributes(attributes)
set_shipments_cost if self.shipments.any?
end
#updating_params = nil
success
end
end
When I run this code, spree never finds #updating_params[:order][:existing_card], even when I select an existing card. Because of that, I can never complete the transaction using a pre-existent card and bogus gateway(gives me empty blanks errors instead).
I tried to bind the method in order_decorator.rb using pry and noticed that the [:existing_card] is actuality at #updating_params' level and not at #updating_params[:order]'s level.
When I delete the decorator, the original code just works fine.
Could somebody explain to me what is wrong with my code?
Thanks,
The method you want to redefine is not really the method of the Order class. It is the method that are mixed by Checkout module within the Order class.
You can see it here: https://github.com/spree/spree/blob/master/core/app/models/spree/order/checkout.rb
Try to do what you want this way:
Create file app/models/spree/order/checkout.rb with code
Spree::Order::Checkout.class_eval do
def self.included(klass)
super
klass.class_eval do
def update_from_params(params, permitted_params, request_env = {})
...
...
...
end
end
end
end

Ruby on Rails: doing a find on reference

I have two tables (nodes and agents). nodes are belong_to agents. I have a script that is pulling the Rails project into it and I'm trying to pull in values from the ActiveRecord. I'm assuming what I'm asking should work whether it's in a controller or view -or- in a cli script. So, my script looks thusly:
#!/usr/bin/env ruby
require '/Users/hseritt/devel/rails_projects/monitor_app/config/environment'
banner = "Banner running..."
script_dir = '/devel/rails_projects/monitor_app/monitor/bin'
class Runner
attr_accessor :banner, :agents, :agent_module, :nodes
def initialize(banner, script_dir)
#banner = banner
#agents = Agent.all
#nodes = Node.all
#script_dir = script_dir
end
def run
puts #banner
#agents.each do |agent|
if agent.active?
agent_module = '%s/%s' % [#script_dir, agent.name]
require agent_module
#nodes.each do |node|
if node.agent == agent
puts node.name
end
end
#
# HERE IS THE ISSUE:
# ns = Node.find_by_agent_id(agent.id)
# ns.each do |node|
# puts node.name
# end
#
# yields this error:
#`method_missing': undefined method `each' for #<Node:0x007fe4dc4beba0> (NoMethodError)
# I would think `ns` here would be itterable but it doesn't seem that way.
end
end
end
end
if $0 == __FILE__
runner = Runner.new(banner, script_dir)
runner.run
end
So, this is in the run method. The block that is not commented out but of course this is not a good solution since each time you iterate through agents you'll have to iterate through nodes each time. The block that is commented out seemed logical to me but throws an error. I'm having trouble probably googling the right thing here I think. What am I missing here?
Node.find_all_by_agent_id
if you don't use "all", it takes the first element only

Rhomobile - load_offline_data issue

I am facing issue with load_offline_data when used to load seed data from .txt files
My code will look like this :
> def initialize
> Rho::RHO.load_all_sources()
> products = Product.find(:all)
> Rho::RhoUtils.load_offline_data(['products'], 'db') end
In db/fixtures/products.txt
source_name|attrib|object|value
Product|name|1|product 1| Product|order_id|1|1|
Product|name|2|product 2|
Product|order_id|2|2|
I am getting error like this :
Application initialize failed: #source_id' for nil:NilClass>;Trace: lib/rho/rhoutils.rb:71:inblock (3 levels) in load_offline_data'
Could any one help me..
Thanks in advance !
Sri, I had to manually require 'rho/rhoutils'.
To avoid the source_id error, I had to call Rhom::Rhom.database_full_reset(true, true). Since this would reset the database every time the application initialized, I included a guard checking that my trees table was already populated.
require 'rho/rhoapplication'
require 'rho/rhoutils'
class AppApplication < Rho::RhoApplication
def initialize
# Tab items are loaded left->right, #tabs[0] is leftmost tab in the tab-bar
# Super must be called *after* settings #tabs!
#tabs = nil
#To remove default toolbar uncomment next line:
###toolbar = nil
super
if Tree.find_all.empty?
Rhom::Rhom.database_full_reset(true, true)
Rho::RhoUtils.load_offline_data(['object_values'], '')
else
puts "*"*80
puts "ALL GOOD"*5
puts "*"*80
end
# Uncomment to set sync notification callback to /app/Settings/sync_notify.
# SyncEngine::set_objectnotify_url("/app/Settings/sync_notify")
# SyncEngine.set_notification(-1, "/app/Settings/sync_notify", '')
end
end

Resources