Rails ERB route helper _path method not found in JSX asset - ruby-on-rails

I'm compiling some JSX assets as part of my Rails 4 app with ReactJS (using the gem) and I'm unable to use route helpers despite including them as specified in these answers.
/railsapp/app/assets/javascripts/components/GigSearchForm.js.jsx.erb:47:in `block in singleton class': undefined local variable or method `gigs_path' for #<#<Class:0x007f80bb0b1df8>:0x007f80bb1528e8> (NameError)
As you can see, the asset is being transformed from ERB to JSX to JS, and while processing the ERB the route helper gigs_path cannot be found. I've already tried implementing solutions such as including an initializer like so:
Rails.application.assets.context_class.class_eval do
include ActionView::Helpers
include Rails.application.routes.url_helpers
end
Sprockets::Context.send :include, Rails.application.routes.url_helpers
Sprockets::Context.send :include, ActionView::Helpers
And at the top of the JSX file including the line: <% environment.context_class.instance_eval { include Rails.application.routes.url_helpers } %>
Nonetheless, I keep getting a similar error that gigs_path is undefined in some manner.

Related

Rails 6 ActionText isn't working on Heroku (undefined method 'rich_text_area_tag')

I am using ActionText to edit a paragraph and it works perfectly locally but when I deploy it to Heroku the page which has the form with rich_text_area it throws an error saying undefined method rich_text_area_tag even though I followed the rails guide. I thought I needed to configure Active Storage on production but that's not the case.
Here is what I am getting in Heroku's logs:
ActionView::Template::Error (undefined method 'rich_text_area_tag' for #<#<Class> Did you mean? rich_text_area)
<%= f.label :something, class:'label' %>
<%= f.rich_text_area :something %>
I found this online, and it was helpful for me:
https://github.com/JoeWoodward/spree_helper_issue
I am not sure if this is the correct way to do it, but it's a temporary workaround.
SOLUTION:
In application_controller.rb enter the following:
require 'action_text'
class ApplicationController < ActionController::Base
helper ActionText::Engine.helpers
...
end
Docs for helper: https://apidock.com/rails/AbstractController/Helpers/ClassMethods/helper
First of all make sure that you have this line in config/application.rb:
require 'rails/all'
If it's a rails 6 app action_text/engine should be loaded.
If it doesn't it's possible taht zeitwerk is not loaded. This happens when you have a rails 5.2 app that was updated to rails 6.
In the same file (config/application.rb) you have to change config.load_defaults to 6.0:
config.load_defaults 6.0
If you want to know what happens in the background take a look at this link on line 125.
To avoid cluttering the ApplicationController code, you can use an initializer:
i.e. add a new file config/initializers/action_text.rb:
ActiveSupport.on_load(:action_view) do
include ActionText::ContentHelper
include ActionText::TagHelper
end
Inspired by p8's comment in a closed Rails issue.

rails - files in autoload_paths folder aren't loaded

I have a app/extensions folder where my custom exceptions reside and where I extend some of the Ruby/Rails classes. Currently there are two files: exceptions.rb and float.rb.
The folder is specified in the ActiveSupport::Dependencies.autoload_paths:
/Users/mityakoval/rails/efo/app/extensions/**
/Users/mityakoval/rails/efo/app/assets
/Users/mityakoval/rails/efo/app/channels
/Users/mityakoval/rails/efo/app/controllers
/Users/mityakoval/rails/efo/app/controllers/concerns
/Users/mityakoval/rails/efo/app/extensions
/Users/mityakoval/rails/efo/app/helpers
/Users/mityakoval/rails/efo/app/jobs
/Users/mityakoval/rails/efo/app/mailers
/Users/mityakoval/rails/efo/app/models
/Users/mityakoval/rails/efo/app/models/concerns
/Users/mityakoval/rails/efo/app/template.xlsx
/Users/mityakoval/.rvm/gems/ruby-2.4.1#web_app/gems/font-awesome-rails-4.7.0.2/app/assets
/Users/mityakoval/.rvm/gems/ruby-2.4.1#web_app/gems/font-awesome-rails-4.7.0.2/app/helpers
/Users/mityakoval/rails/efo/test/mailers/previews
The reason for it to be listed there twice is that it should be automatically loaded since it was placed under app directory and I have also manually added it to the autoload_paths in application.rb:
config.autoload_paths << File.join(Rails.root, 'app', 'extensions/**')
The strange thing is that my exceptions.rb is successfully loaded at all times, but the float.rb isn't unless eager loading is enabled.
Answers to this question say that it might be related to Spring (which I tend to believe), so I've added the folder to spring.rb:
%w(
.ruby-version
.rbenv-vars
tmp/restart.txt
tmp/caching-dev.txt
config/application.yml
app/extensions
).each { |path| Spring.watch(path) }
I've restarted Spring and the Rails server multiple times and nothing worked. Does anyone have any suggestions?
Ruby version: 2.4.1
Rails version: 5.1.5
EDIT
/Users/mityakoval/rails/efo/app/extensions/float.rb:
class Float
def comma_sep
self.to_s.gsub('.', ',')
end
end
rails console:
irb> num = 29.1
irb> num.comma_sep
NoMethodError: undefined method `comma_sep' for 29.1:Float
from (irb):2
A better way to monkeypatch a core class is by creating a module and including it in the class to be patched in an initializer:
# /lib/core_extensions/comma_seperated.rb
module CoreExtensions
module CommaSeperated
def comma_sep
self.to_s.gsub('.', ',')
end
end
end
# /app/initializers/core_extensions.rb
require Rails.root.join('lib', 'core_extensions', 'comma_seperated')
# or to require all files in dir:
Dir.glob(Rails.root.join('lib', 'core_extensions', '*.rb')).each do |f|
require f
end
Float.include CoreExtensions::CommaSeperated
Note that here we are not using the Rails autoloader at all and explicitly requiring the patch. Also note that we are placing the files in /lib not /app. Any files that are not application specific should be placed /lib.
Placing the monkey-patch in a module lets you test the code by including it in an arbitrary class.
class DummyFloat
include CoreExtensions::CommaSeperated
def initialize(value)
#value = value
end
def to_s
#value.to_s
end
end
RSpec.describe CoreExtensions::CommaSeperated do
subject { DummyFloat.new(1.01) }
it "produces a comma seperated string" do
expect(subject.comma_sep).to eq "1,01"
end
end
This also provides a much better stacktrace and makes it much easier to turn the monkey patch off and on.
But in this case I would argue that you don't need it in the first place - Rails has plenty of helpers to humanize and localize numbers in ActionView::Helpers::NumberHelper. NumberHelper also correctly provides helper methods instead of monkeypatching a core Ruby class which is generally best avoided.
See:
3 Ways to Monkey-Patch Without Making a Mess

How To Use Spree Route Helpers in RSpec

I am trying to use the Spree 2.3 route helpers in Rspec 3.0. In the main app, I can access them by prefixing spree., like so:
spree.admin_login_path => 'spree/admin/user_sessions#new'
However I can't seem to access them in Rspec.
#rspec error
undefined local variable or method `spree_admin_login_path'
I've found reference to including the helpers in the rails_helper file, but this throws an error
# app/spec/rails_helper.rb
RSpec.configure do |config|
config.include Spree::Core::UrlHelpers
end
# configuring the above results in the following
app/spec/rails_helper.rb:21:in `block in <top (required)>': uninitialized constant Spree (NameError)
How do I access the spree routes given in $ rake routes in my tests?
After digging through the Spree code I was able to put together this setup for my rails_helper file that lets me use spree routes such as spree.admin_login_path in my spec files:
# app/spec/rails_helper.rb
require 'spree/testing_support/url_helpers'
RSpec.configure do |config|
config.include Spree::TestingSupport::UrlHelpers
end
I'm sure there's a smoother way to include all of Spree's test helpers, and I'd love to hear about it from someone who knows.

Sprockets not adding fingerprint to files added in scss file

I'm having an issue with Rails, Sprockets, SCSS and them not adding a fingerprint to the generated image files.
When I try to precompile my assets in an environment other than development, I get the following error:
rake aborted!
Custom asset_path helper is not implemented
Extend your environment context with a custom method.
environment.context_class.class_eval do
def asset_path(path, options = {})
end
end
So I add the following to an initializer:
Rails.application.assets.context_class.class_eval do
def asset_path(path, options = {})
end
end
Which causes the error to go away, although I don't know if this is the right way about fixing the issue. It then produces a new error:
undefined method `include?' for nil:NilClass
However, if I add the following code:
Rails.application.assets.context_class.class_eval do
def asset_path(path, options = {})
"/assets/#{path}"
end
end
It precompiles fine, but then the generated css does not have the fingerprint generated at the end of the url and therefore doesn't load when viewing the page.
The weird thing is that images that aren't added in a scss file, like in an img tag in the html, has the fingerprint appended fine and shows up when viewing the page.
Here is an example of some scss that doesn't load the fingerprint:
background: $blue url( asset-path('hero/hero-bg.jpg') ) repeat-x;
I'm running Rails 4.0.2. Here is my gemfile: https://gist.github.com/anthonycollini/8025540
Any help would be greatly appreciated. Thank you.
You shouldn't have to define asset_path since that is a helper that is already provided by Rails. It looks like you may have missed <%= %> when using asset_path in your scss file.
background: $blue url(<%= asset-path('hero/hero-bg.jpg') %>) repeat-x;
Also, don't forget to add the .erb file extension on your scss file like example.css.scss.erb.
Hope that helps!

Accessing rails_admin url helpers from Rspec files

I am using Rails 3.2, RailsAdmin 0.0.3, Rspec and Capybara.
I try to call RailsAdmin url helpers from my spec file as it is explained in the RailsAdmin wiki. rails_admin.new_path(:model_name => :user)
When I use the helper that way from a controller or a view it works nice but when trying to use it from a spec file it gives this error:
undefined local variable or method `rails_admin' for #RSpec::Core::ExampleGroup::Nested_2:0xbe04948>
I guess that I have to add something to my spec_helper.rb file in order to load rails_admin. But after googling for a while and looking to rails_admin gem's spec_helper, I cannot figure out what...
Any help will be apreciated!
I found it in spec_helper.rb of rails_admin.
Include the following code into spec_helper.rb.
RSpec.configure do |config|
...
config.include RailsAdmin::Engine.routes.url_helpers
end
I tested using debugger. It can be called
> new_path(:model_name => :user)
=> "/admin/user/new"
I added this line to individual specs that needed rails_admin urls and it allowed me to reference the methods mentioned in a prior post, but without interfering with my non-admin urls.
include RailsAdmin::Engine.routes.url_helpers
Example of method within spec
index_path(:model_name => :client)
I am using Rails 5.0, Rspec 3.5 and Capybara 2.10.1

Resources