Spree Order checkout_flow not transitioning - ruby-on-rails-5

Order checkout flow is not transitioning when I have a order decorator file in my app folder.
# app/models/spree/order_decorator.rb
Spree::Order.class_eval do
checkout_flow do
go_to_state :payment, if: ->(order) { order.payment? || order.payment_required? }
go_to_state :complete
end
end
It only works when I move the order decorator file to lib folder and require the file in initializers folder.
# lib/models/spree/order_decorator.rb
Spree::Order.class_eval do
checkout_flow do
go_to_state :payment, if: ->(order) { order.payment? || order.payment_required? }
go_to_state :complete
end
end
# config/initializers/spree.rb
require "#{Rails.root}/lib/models/spree/order_decorator"
Environment
Version used: Spree 3.3.6
*Ruby version: 2.5.3
*Rails version: 5.1.7
In application.rb
# config/application.rb
config.to_prepare do
# Load application's model / class decorators
Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
Rails.configuration.cache_classes ? require(c) : load(c)
end
# Load application's view overrides
Dir.glob(File.join(File.dirname(__FILE__), "../app/overrides/*.rb")) do |c|
Rails.configuration.cache_classes ? require(c) : load(c)
end
end

Related

method missing when test helper

I want to create a gem which can add some helper method to rails:
module SharpAssets
class Railtie < Rails::Railtie
initializer "my_railtie.configure_rails_initialization" do |app|
app.middleware.use ::ActionDispatch::Static, "public"
ActionView::Base.send :include, ViewHelpers
end
config.to_prepare do
ActionView::Helpers.class_eval do
#ActionView::Base.send :include, SharpAssets::ViewHelpers
end
end
end
module ViewHelpers
#include Generators::Pagedown
puts "initializer my_railtie.configure_rails_initialization"
def sharp_assets
"sharp_assets"
end
end
end
and my test case is:
require 'test_helper'
class SharpAssetsTest < ActionView::TestCase
test "pagedown_tag be html safe" do
assert sharp_assets, ""
end
end
and my test_helper is :
# Configure Rails Environment
ENV["RAILS_ENV"] = "test"
require File.expand_path("../dummy/config/environment.rb", __FILE__)
require "rails/test_help"
Rails.backtrace_cleaner.remove_silencers!
# Load support files
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
# Load fixtures from the engine
if ActiveSupport::TestCase.method_defined?(:fixture_path=)
ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
end
and my gem's directory is:
The error is
NameError: undefined local variable or method `sharp_assets' for #<SharpAssetsTest:0x007ffe3c5abf08>
Did you required your lib in your test_helper.rb?

rails carrierwave / s3 signature doesn't match. Wrong private key

I'm trying to get carrierwave working with S3, and I am getting a signature doesn't match error. The weird thing is that it doesn't look like carrierwave is sending the right secret key. In the error, the post is given as:
"Authorization"=>"AWS AKIAIOLWQKSJFH6E3I5Q:vKgyAw2z4c8zzqGWoxLUbw7I5oI="
Which I assume is supposed to be my publickey:privatekey. The thing is that vKgyAw2z4c8zzqGWoxLUbw7I5oI= is not the private key I have stored in fog.rb. Is that right?
Any help is appreciated.
Request/Response:
request => {:chunk_size=>1048576, :connect_timeout=>60, :headers=>{"Content-Length"=>1557, "Content-Type"=>"image/
gif", "x-amz-acl"=>"public-read", "Date"=>"Wed, 24 Oct 2012 12:45:17 +0000", "Authorization"=>"AWS AKIAIOLWQKSJFH6E3
I5Q:vKgyAw2z4c8zzqGWoxLUbw7I5oI=", "Host"=>"s3.amazonaws.com:443"}, :instrumentor_name=>"excon", :mock=>false, :nonb
lock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_ca_file=>"/home/tim/.rvm/gems/ruby-1.9.3-p194/gems/excon-0.16.5
/data/cacert.pem", :ssl_verify_peer=>true, :write_timeout=>60, :host=>"myeasybnb.s3.amazonaws.com", :host_port=>"s3.
amazonaws.com:443", :path=>"/images%2Fb1bb6639-dc08-4981-9a9b-7175093ac970.gif", :port=>"443", :query=>nil, :scheme=
>"https", :body=>#<File:/home/tim/Dropbox/myeasybnb/tmp/uploads/20121024-0845-20225-1170/240x240.gif>, :expects=>200
, :idempotent=>true, :method=>"PUT"}
response => #<Excon::Response:0xa7a1098 #body="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>SignatureD
oesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your
key and signing method.</Message>
fog.rb:
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS', # required
:aws_access_key_id => 'AKIAIOLWQKSJFH6E3I5Q', # required
:aws_secret_access_key => '[my secret key]' # required
}
config.fog_directory = 'myeasybnb' # required
config.fog_public = true # optional, defaults to true
end
Uploader.rb:
# encoding: utf-8
class PhotoUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
include CarrierWave::MiniMagick
# Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
include Sprockets::Helpers::RailsHelper
include Sprockets::Helpers::IsolatedHelper
# Choose what kind of storage to use for this uploader:
# storage :file
storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"images"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
class MyUploader < CarrierWave::Uploader::Base
def default_url
asset_path("seeds/" + [version_name, "default.png"].compact.join('_'))
end
end
# Process files as they are uploaded:
# process :scale => [200, 300]
#
# Create different versions of your uploaded files:
process :convert => 'jpg'
version :sidecarousel, :if => :is_side_carousel? do
process :resize_to_fit => [2000,1000]
end
version :thumbnail, :if => :is_thumbnail? do
process :resize_to_fill => [240,240]
end
version :linetext, :if => :is_line? do
process :resize_to_fill => [400,200]
end
version :carousel, :if => :is_carousel? do
process :resize_to_fit => [2200, 1000]
end
version :phone do
process :resize_to_fit => [900,900]
end
# def scale(width, height)
# # do something
# end
def is_side_carousel? photo
model.location == 1
end
def is_thumbnail? photo
model.location == 2
end
def is_line? photo
model.location == 3
end
def is_carousel? photo
model.location == 4
end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(jpg jpeg gif png)
end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
def filename
file.nil? ? #filename = nil : #filename = "#{secure_token}.#{file.extension}"
end
def secure_token
var = :"##{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
end
def cache_dir
"#{Rails.root}/tmp/uploads"
end
end
I managed to fix this. I'm not exactly sure what I did, but there was a couple issues. (1) I think I was getting the auth error because I was specifying a folder in my uploader. Now, I set my directory in the uploader to "" and specify the folder through the fog configuration.
(2) Another error I was getting was a time mismatch. I run mint in a virtual machine for development, and the time was different from reality. Amazon threw an error at that. Once I set the correct time, that went away.

Allow my own class in Rails to be configured with block syntax

I often see code of the form
RSpec.configure do |config|
config.include ApiHelper
# ## Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
config.include FactoryGirl::Syntax::Methods
end
Is there a feature in Rails that lets me do something similar? I want to be able to configure my own library with a similar syntax within config/initializers/my_class.rb
MyClass.configure do |config|
# allow configuration here
end
Nothing special is needed in Rails - it is simple Ruby code. Here is how it can be done:
class MyClass
def self.configure(&block)
a_hash = { :car => "Red" }
puts "Hello"
yield a_hash
puts "There"
end
end
MyClass.configure do |config|
puts "In Block"
puts config[:car]
end
Output:
Hello
In Block
Red
There
I am yielding a hash, but you can yield whatever object you want to.
Rails will load all the Ruby files in the config/initializers directory when starting up the server.
If you want to use the same style for your own custom configurable class then you just have to implement a configure class method that accepts a block and passes a configuration object to that block. e.g.
class MyClassConfiguration
# configuration attributes
end
class MyClass
def self.configure
yield configuration if block_given?
end
def self.configuration
#config ||= MyClassConfiguration.new
end
end
Using phoet's gem would be even easier.
Its worth taking a look at how RSpec does it if you are curious:
The RSpec.configure method is in https://github.com/rspec/rspec-core/blob/master/lib/rspec/core.rb
The Configuration class is implemented in https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/configuration.rb
i don't know if rails provides a helper for that, but i wrote my own tiny solution for this problem that i use in several gems: https://github.com/phoet/confiture
it let's you define configurations:
module Your
class Configuration
include Confiture::Configuration
confiture_allowed_keys(:secret, :key)
confiture_defaults(secret: 'SECRET_STUFF', key: 'EVEN_MOAR_SECRET')
end
end
and have an easy api to do the configuration:
Your::Configuration.configure do |config|
config.secret = 'your-secret'
config.key = 'your-key'
end
besides this, there are a lot of other config tools out there like configatron or simpleconfig.
A global configuration set via the block.
module VkRobioAPI
module Configuration
OPTION_NAMES = [
:client_id,
:redirect_uri,
:display,
:response_type
]
attr_accessor *OPTION_NAMES
def configure
yield self if block_given?
self
end
end
end
module VkRobioAPI
extend VkRobioAPI::Configuration
class << self
def result
puts VkRobioAPI.client_id
end
end
end
Example:
VkRobioAPI.configure do |config|
config.client_id = '3427211'
config.redirect_uri = 'bEWLUZrNLxff1oQpEa6M'
config.response_type = 'http://localhost:3000/oauth/callback'
config.display = 'token'
end
Result:
VkRobioAPI.result
#3427211
#=> nil
If you are using rails, you can just include ActiveSupport::Configurable into your class and off you go. Outside of rails, you will have to add the activesuport gem to your Gemfile or gemspec and then call require 'active_support/configurable'.
Example
class MyClass
include ActiveSupport::Configurable
end
Usage
With block
MyClass.configure do |config|
config.key = "something"
config.key2 = "something else"
end
or inline, without block
MyClass.config.key = "something"
MyClass.config.key2 = "something else"
or like a hash
MyClass.config[:key] = "somehting"
MyClass.config[:key2] = "something else"
Note: key can be any character of your choice.

Converting to modular sinatra app breaks tests

I've modularised by classic sinatra app and moved my routes in my sinatra app into individual routes files as per https://stackoverflow.com/a/5030173/111884, however, I can't seem to get my tests working.
This is what my files look like:
./web.rb
require 'sinatra'
require 'sinatra/flash'
class MyApp < Sinatra::Application
# ...
end
require_relative 'models/init'
require_relative 'helpers/init'
require_relative 'routes/init'
./routes/init.rb
require_relative 'main'
./routes/main.rb
# The main routes for the core of the app
class MyApp < Sinatra::Application
get '/' do
erb :main
end
end
./spec/spec_helper.rb
ENV['RACK_ENV'] = 'test'
require 'minitest/autorun'
require 'rack/test'
require 'factory_girl'
# Include factories.rb file
begin
require_relative '../test/factories.rb'
rescue NameError
require File.expand_path('../test/factories.rb', __FILE__)
end
# Include web.rb file
begin
require_relative '../web'
rescue NameError
require File.expand_path('../web', __FILE__)
end
./spec/web_spec.rb
begin
require_relative 'spec_helper'
rescue NameError
require File.expand_path('spec_helper', __FILE__)
end
include Rack::Test::Methods
def app() Sinatra::Base end
describe "Some test" do
# ...
end
Rakefile
# Test rake tasks
require 'rake/testtask'
Rake::TestTask.new do |t|
t.libs << "test"
t.libs << "spec"
t.test_files = FileList['test/factories.rb', 'test/test_*.rb', 'spec/spec_helper.rb', 'spec/**/*_spec.rb']
t.verbose = true
end
The output of the tests is:
<h1>Not Found</h1>
It doesn't seem to be loading the ./routes/*.rb files.
I'm using Sinatra::Application, instead of Sinatra::Base, but https://stackoverflow.com/a/5030173/111884 uses it. It also references it here http://www.sinatrarb.com/extensions.html. I have tried changing it to use Sinatra::Base, but it didn't fix it.
I've also tried Sinatra tests always 404'ing and Using Cucumber With Modular Sinatra Apps, but they don't work.
I think you just need to change your app method to return your modularised application class (MyApp) rather than the Sinatra::Base class. So replace:
def app() Sinatra::Base end
in web_spec.rb, with:
def app
MyApp
end
Rack::Test::Methods depends on the app method to tell it which class to call to process requests. In a simple non-modular Sinatra application that class is Sinatra::Base because that is the class in which the routes are applied by default. In a modular application that is the class in which you define your routes (MyApp in your case).

Is it possible to "watch" Haml files in Compass (stylesheet authoring tool)?

Currently, Compass is watching the .scss files inside the src folder and automatically updating the cs files. (by typing compass watch myproject).
Is there any way of including haml files in the "watching process"?
(I couldn't install StaticMatic because I don't want to install Ruby1.8).
Firstly, you should be using RVM. Installing any version of Ruby becomes painless.
Secondly, I just wrote this for myself, using the same 'fssm' gem that Compass uses to watch files. Add this to your / create a Rakefile:
require 'rubygems'
require 'fssm'
require 'haml'
class HamlWatcher
class << self
def watch
refresh
puts ">>> HamlWatcher is watching for changes. Press Ctrl-C to Stop."
FSSM.monitor('haml', '**/*.haml') do
update do |base, relative|
puts ">>> Change detected to: #{relative}"
HamlWatcher.compile(relative)
end
create do |base, relative|
puts ">>> File created: #{relative}"
HamlWatcher.compile(relative)
end
delete do |base, relative|
puts ">>> File deleted: #{relative}"
HamlWatcher.remove(relative)
end
end
end
def output_file(filename)
# './haml' retains the base directory structure
filename.gsub(/\.html\.haml$/,'.html')
end
def remove(file)
output = output_file(file)
File.delete output
puts "\033[0;31m remove\033[0m #{output}"
end
def compile(file)
output_file_name = output_file(file)
origin = File.open(File.join('haml', file)).read
result = Haml::Engine.new(origin).render
raise "Nothing rendered!" if result.empty?
# Write rendered HTML to file
color, action = File.exist?(output_file_name) ? [33, 'overwrite'] : [32, ' create']
puts "\033[0;#{color}m#{action}\033[0m #{output_file_name}"
File.open(output_file_name,'w') {|f| f.write(result)}
end
# Check that all haml templates have been rendered.
def refresh
Dir.glob('haml/**/*.haml').each do |file|
file.gsub!(/^haml\//, '')
compile(file) unless File.exist?(output_file(file))
end
end
end
end
namespace :haml do
desc "Watch the site's HAML templates and recompile them when they change"
task :watch do
require File.join(File.dirname(__FILE__), 'lib', 'haml_watcher')
HamlWatcher.watch
end
end
Run it with:
rake haml:watch