Spree Commerce extending helpers - ruby-on-rails

I am attempting to extend one of the helper modules which Spree Commerce offers. I came across the following file: spree/frontend/app/helpers/frontend_helper.rb
Ultimately what I am trying to do is add a simple helper method to this module. I plan to call this helper method for use with the single product page. My implementation seems to be working fine with a couple exceptions, which has led me to believe that I have screwed up somewhere. Here is what I have done:
I have the file app/helpers/spree/frontend_helper_decorator.rb. The contents of this file:
Spree::FrontendHelper.module_eval do
# Create Variant Matrix
def create_variant_matrix( variants )
#valid_variants = {}
...
#valid_variants
end
end
The next thing I have done is extended the Products Controller for the purpose of overwriting one of the methods. I created app/controllers/spree/products_controller_decorator.rb. The content of this file:
Spree::ProductsController.class_eval do
include Spree::FrontendHelper
# Overwrite Show to include variant matrix
def show
#variants = #product.variants_including_master.active(current_currency).includes([:option_values, :images])
#product_properties = #product.product_properties.includes(:property)
#taxon = Spree::Taxon.find(params[:taxon_id]) if params[:taxon_id]
#vMatrix = create_variant_matrix( #variants )
end
end
As you can see here, I have overwritten the show method, copied the code from the default spree method and added my custom call. I have also included the FrontendHelper module in the controller.
This works without any errors with few exceptions. When I run bundle for the purpose of installing a new gem for instance, I typically get an error which requires me to remove my custom FrontendHelper method completly before I can successfully install the gem. Once the gem is installed, I add the code back in and it works fine. The error I receive is:
/fake/path/app/controllers/spree/product_controller_decorator.rb:2:in `block in <top (required)>': uninitialized constant Spree::FrontendHelper (NameError)
I have tried searching for this error with no luck. I am fairly new to Ruby (background is in PHP), but based on the tutorials I followed, I feel that it is correct. It also seems to be working properly in most scenarios.
Any help is appreciated.

Related

How to monkeypatch ActiveRecord::QueryMethods?

I'm trying to monkeypatch a method onto ActiveRecord::QueryMethods which augments the select clause instead of replacing it entirely.
I tried:
# config/initalizers/select_also.rb
module SelectAlso
def select_also(*fields)
select(self.select_values + fields)
end
end
ActiveRecord::QueryMethods.include(SelectAlso)
But this gives me:
/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/active_support.rb:79:in `block in load_missing_constant': uninitialized constant ActiveRecord::Relation::QueryMethods (NameError)
I don't get where its getting the constant ActiveRecord::Relation::QueryMethods from at all since i'm not referencing it.
The reason I'm doing it as a monkeypatch is that I want to try it out as a potential PR / feature request to rails itself without working on the rails source and dealing with setting up a sample app.
The use case is where you want to add something like aggregates or joined columns without recreating the entire select clause:
User.joins(:answers)
.select_also('AVG(answers.score) AS average_score')
Instead of:
User.joins(:answers)
.select('users.*','AVG(answers.score) AS average_score')
Or some hacky solution that introspects on the table.
You might want to consider ActiveRecord::QueryMethods#extending as an alternative to monkey-patching - it's designed to extend a scope with additional methods.
module Pagination
def page(number)
# pagination code goes here
end
end
scope = Model.all.extending(Pagination)
scope.page(params[:page])
Rails also supports applying extensions to associations which is pretty neat.

uninitialized constant ActiveStorage::Identification::Net

I have ActiveStorage set up on a new project and it's successfully saving the files that are selected in development, but when they are submitted, I get this error on the update action:
uninitialized constant ActiveStorage::Identification::Net
With the offending code in the controller being:
#entry.attributes = wiki_params
It's set as an instance variable here then I merge in other values, then call update_attributes on the whole thing.
My white list looks like:
def wiki_params
params.require(:wiki).permit(:content, :category, :new_category, :title, files: [])
end
The files are actually uploading fine and displaying fine afterwards in the view, it's just this line in the update that squawks.
I found this GH issue that is specific to Azure and adds require "net/http". If I require that at the top of the controller it works without complaining.
I'm assuming requiring net/http on the controller is not the expected behavior, but I'm curious why this works and if I have something else set up incorrectly to need this at all.
It looks like we were missing a require in this file. I added it here. The next release candidate for 5.2.0 will include the fix. Sorry!

RoR Mailboxer Monkey Patch works only a few times

I am adding a method to Mailboxer::Conversation to retrieve a link using mailboxer's emails to reply (i.e. reply_link).
I've decided to monkey patch mailboxer within my application. What I've done exactly is the following:
Created the folder structure lib/mailboxer/extensions.
Added files lib/mailboxer/extensions/conversation.rb, lib/mailboxer/extensions.rb, lib/mailboxer.rb.
The following is the content of the files:
# lib/mailboxer/extensions/conversation.rb
module Mailboxer
module Extensions
module Conversation
def reply_link
"/mail?notif_id=#{id}"
end
end
end
end
# lib/mailboxer/extensions.rb
require 'mailboxer/extensions/conversation'
# lib/mailboxer.rb
require 'mailboxer/extensions'
My config/application.rb has the following:
config.autoload_paths += %W(#{config.root}/lib)
Which gives me access to my lib folder.
Then what I do is include Mailboxer::Extensions::Conversation to Mailboxer::Conversation within the mailboxer initializer file initalizers/mailboxer.rb:
Mailboxer.setup do |config|
# ...
end
Mailboxer::Conversation.include Mailboxer::Extensions::Conversation
In my rails console, the code always works. However in the website, the reply_link method works at first, then becomes undefined randomly.
Couple of attempts later....
and it stops working until I restart the server...
Whenever I get an unrelated exception (i.e. typo, refactoring, etc.) the reply_link method becomes undefined. Could this be a development thing?
I could fork mailboxer, make my changes then go on. But the method is so custom to my application that I'd rather just patch.
If anyone has any suggestions, advice or questions I truly appreciate the advice.
First, I am still convinced that this is a development issue only. Whenever I have time to spare, I will test this out and post here.
Second, to ensure this never happened again I copied the source for the Mailboxer's Conversation and added an inclusion include MailboxerExt::Conversation.
I also structured my extension to not collide, reload Mailboxer's namespace.
The final result has the folders app/models/mailboxer, lib/mailboxer_ext.
The files are app/models/mailboxer/conversation.rb, lib/mailboxer_ext.rb and lib/mailboxer_ext/conversation.rb.

rails current_teacher keyword not set

I'm new to Ruby on Rails and I'm looking at an application that has a variable called current_teacher. I cannot seem to find where this is set. Everywhere I look the code seems to read from it but where is it set. Is this one of those things that Rails does for you. There is a mode and a table called teachers, so I'm sure this has something to do with it.
I'm very confused by statements like the following, can someone tell me how Rails does this?
if current_teacher.can_request_fieldtrip
Suppose you have a controller like :
class ClientsController < ApplicationController
  def new
if current_teacher.can_request_fieldtrip
# code
end
  end
end
Here is debugging tips :
(a) put this in your Gemfile and do bundle install :
`gem 'pry-rails', :group => :development`
(b) Put the line binding.pry just before the if statement.
(c) Start rails server using rails s.
(d) Hit the browser like http://localhost:3000/new
(e) Now you will be in the Pry console. Just do in the console,
method(:current_teacher).source_location
And the above line tell you where the method has been defined.
Documentation of Method#source_location
Returns the Ruby source filename and line number containing this method or nil if this method was not defined in Ruby (i.e. native)
Rails does not support authentication by itself, however there are a lot of 'add-ons' that rails can use. These 'add-ons' are called gems. This can be a little confusing because you can't actually see their code inside your project folder.
If you open a file called "Gemfile" (it should be in your project folder) you can see a list of gems that you use. Try searching their names on google, you will probably find official web page that contains it's documentation. That way can learn what they do and how to use them.
current_teacher method smells like "Devise" gem
https://github.com/plataformatec/devise
I'm not sure about can_request_fieldtrip, this could be a custom method defined in Teacher model.

uninitialized constant UploadsController::Bucket when trying to write general AWS::S3 Upload controller

I'm trying to write a general Amazon S3 uploader (will be used mostly for images) for my rails project. I was able to set up the environment in my console following http://amazon.rubyforge.org/.
I was able to follow the guide in the console. However, I had trouble when I applied it to my rails project. When I try to access my new view, I get the following error:
NameError in UploadsController#new
uninitialized constant UploadsController::Bucket
Here is my controller:
class UploadsController < ApplicationController
require 'aws/s3'
def new
photo_bucket = Bucket.find('photos')
#photos = photo_bucket.objects
end
def create
file = 'black-flowers.jpg'
S3Object.store(file, open(file), 'photos')
end
end
In my controller, my new action will contain the form for the upload and a list of all the photos.
My create action will just save the file. I haven't figured out how the params from the form will be passed into the controller yet, so ignore the 'black-flowers.jpg' line.
My guess is that I did not establish a connection in the controller.
How do I establish a connection or fix this error?
Thanks for looking.
Bucket is not a top level constant in this case. You probably want the AWS::S3::Bucket constant for new, and I'd assume something similar for S3Object.
Note that you may also want to look into the Fog library for this.
The fact that you haven't figured out how params will be passed in implies that you may also want to work through the Rails tutorials without S3 first.
I had a similar issue and it was solved by just checking all files required were provided and restarting the server

Resources