How to delete a helpers file in Rails 5? - ruby-on-rails

I'm new to Rails, and after using rails g controller Users to generate a users controller, I decided to remove (i.e., rm) the generated helper in app/helpers/users.rb, because I realized I didn't need it. It seems ugly to keep a bunch of empty files around to me. This broke my app. When I try to visit any page in my, or run a test, I get this error: Couldn't find UsersHelper, expected it to be defined in helpers/users_helper.rb.
I fixed it by manually re-creating that file, but how do I get rid of it? Is that just not supported?
Edits based on questions people asked
The helper does not appear to be referenced explicitly anywhere, grep -Ri UsersHelper . only returns results for the module itself and a bootsnap cache file. The same command with :helper 'user' or 'helpers/users' returns nothing.

If Rails is telling you that it can't find UsersHelper then it means that the module is called somewhere else in the project. When the page shows you the couldn't find message, it should also indicate the offending file where UsersHelper is being included (same with the test output). If you remove this reference, you should have no problem removing the module (or directory).

I sort of figured out the issue, but I still don't understand it.
I am using some url helper functions: user_url(:id) and new_user_url, and these apparently require the helpers to exist even though they are not explicitly defined there. If anyone can explain in more depth what's going on, I'd appreciate it.

Related

Rails: Can't access a module in my lib directory

I'd like to create a general purpose string manipulation class that can be used across Models, Views, and Controllers in my Rails application.
Right now, I'm attempting to put a Module in my lib directory and I'm just trying to access the function in rails console to test it. I've tried a lot of the techniques from similar questions, but I can't get it to work.
In my lib/filenames.rb file:
module Filenames
def sanitize_filename(filename)
# Replace any non-letter or non-number character with a space
filename.gsub!(/[^A-Za-z0-9]+/, ' ')
#remove spaces from beginning and end
filename.strip!
#replaces spaces with hyphens
filename.gsub!(/\ +/, '-')
end
module_function :sanitize_filename
end
When I try to call sanitize_filename("some string"), I get a no method error. When I try to call Filenames.sanitize_filename("some string"), I get an uninitilized constant error. And when I try to include '/lib/filenames' I get a load error.
Is this the most conventional way to create a method that I can access anywhere? Should I create a class instead?
How can I get it working? :)
Thanks!
For a really great answer, look at Yehuda Katz' answer referenced in the comment to your question (and really, do look at that).
The short answer in this case is that you probably are not loading your file. See the link that RyanWilcox gave you. You can check this by putting a syntax error in your file - if the syntax error is not raised when starting your app (server or console), you know the file is not being loaded.
If you think you are loading it, please post the code you are using to load it. Again, see the link RyanWilcox gave you for details. It includes this code, which goes into one of your environment config files:
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]
But really, read Yehuda's answer.

Losing namespace information in a rails namespaced model

When you create a namespaced model with rails scaffolding, you get two files. For example, this scaffold:
rails generate model Staff::Location name:string address:string
Generates these files:
/app/models/staff.rb
module Staff
def self.table_name_prefix
"staff_"
end
...
/app/models/staff/location.rb
class Staff::Location < ActiveRecord::Base
...
I am running into problems when in development mode where rails unloads the Staff module and never reloads it. This causes several annoying bugs such as Location not able to access it's table due to the missing table_name_prefix. The problem seems to crop up when I don't access the models directly, such as through a polymorphic relationship.
I can't seem to get the module loaded on a consistent basis. Is this the best practice way to do namespaced models? If it is, what am I missing?
Although I wasn't able to reproduce the problem in Rails 3.2.2, I've run into something like this before. The generic way to hack around this problem in development mode is through an ActionDispatch callback. Add this to config/environments/development.rb:
MyApp::Application.configure do
ActionDispatch::Callbacks.before do
load Rails.root.join('app', 'models', 'staff.rb')
end
end
Anything you do in that block will be executed before each request, so make sure you're only doing it in development mode.† Otherwise, you're going to suffer a performance hit in production.
I logged a message inside the staff.rb file and within the Staff module itself, and both messages appeared in the log for each request.
† I tried using the to_prepare callback, since that seems to be the documented way to execute code before each request only when cache_classes is false. But that only seemed to execute after restarting the application. There's at least one other open Stack Overflow question regarding this, although he's using a slightly different syntax than I used. If you can get to_prepare to work, I'd suggest that instead of before.
About a year later, I have finally found the answer to this question. This answer is specifically for rails 3.1. I am not sure if it is a problem in rails 3.2.
The problem occurs when setting up a model. If scaffolding is used, no helper file is generated. This would normally be in /app/helpers/staff/location_helper.rb. There are two ways to setup this file:
module Staff::LocationHelper
...
end
module Staff
module LocationHelper
...
end
end
In rails 3.1, specifically for helpers, you must use the first solution. You do not have to use it for other modules that use a namespace in other parts of the rails project. In fact, some structures in ruby require the second solution.
If you use the second solution when declaring a helper, in certain cases the Staff module in the helper file will override the module in /app/models/staff.rb. It will silently replace it with the empty Staff module in the file. This does not happen 100% of the time because helpers are not always loaded.

Override a method inside a gem from another gem

Ok, I have a rails gem that I am working on and I want it to override a specific method in sprockets.
The method I want to override is: Sprockets::Base.digest so that I can base the fingerprint off my gem version when compiling the app's assets.
How would I go about doing that?
In my gem I create a file lib/sprockets/base.rb and place the following code:
class Sprockets::Base
def digest
#digest = digest_class.new.update(MyGem::VERSION)
#digest.dup
end
end
When I run bundle exec rake assets:precompile I get:
undefined method 'logger=' for #<Sprockets::Environment:0x1315b040>
So it almost seems to me like the entire class is getting overridden somehow (this losing that, and the other methods), instead of just overriding the one method.
If I include that snippet of code directly into the app's rakefile that's using both gems, things work perfectly.
It's impossible to override an entire Ruby class in that manner, but I think it is possible to prevent the original class from loading...if it's using autoload. I was curious, so I checked out https://github.com/sstephenson/sprockets/blob/master/lib/sprockets.rb, and yes, Sprockets is using autoload.
autoload :Base, "sprockets/base"
Importantly, that doesn't load the code. It simply tells Ruby that if/when an undefined constant called "Sprockets::Base" is ever encountered, to load it from the specified file. Your patch defines Sprockets::Base before it is ever called anywhere, thus preventing the original file from loading.
When you moved your patch to the Rakefile, something in Rails had already referenced Sprockets::Base, loading the original code. Your patch then applied cleanly on top.
I've never actually used autoload, so I'm not sure how cases like this are supposed to be handled. I'm betting though, that this would work:
Sprockets::Base
class Sprockets::Base
def digest
...
By referencing the class first, you should force Ruby to load the original class. Then you can safely go about the business of overriding one of its methods.
Ok, I marked your answer correct, but it really only led me to figure out the problem.
Anyway, the rails app was requiring my base file instead of the one in the gem itself. Which is what you said. However, the reason it was happening seems to have been caused by the path itself. The path to the file was basically the same as the gem's (lib/sprockets/base.rb).
Moving that file into my gem's "namespace" (lib/my_gem instead of lib/sprockets) and renaming it to sprockets_base.rb fixed the problem! Weird, huh?
In other words, me trying to keep the directory structure nice actually seems to have confused Rails into thinking it was the gem itself or something.

Accessing the app name from inside a rails template when generating rails app

I'm messing around with rails 2.3 templates and want to be able to use the app name as a variable inside my template, so when I use...
rails appname -m path/to/template.rb
...I want to be able to access appname inside template.rb. Anyone know how to do this?
Thanks
I was looking for an answer to this question. unfortunately the answer above (#root) doesn't seem to work in Rails 3.
Here's the variables you can access in Rails 3 app templates (even easier):
#app_name
#app_path
Thanks for the answers. Mike Woodhouse, you were so close. Turns out, all you need to do to access the appname from inside your rails template is...
#root.split('/').last
The #root variable is the first thing created when initializing templates and is available inside your rails templates. RAILS_ROOT does not work.
In Rails 3, use the app_name attribute.
See the documentation for the Rails::Generators::AppGenerator.
I ran into a similar problem, none of the variables listed above were available to me in Rails 4. I found that #name was available while running
rails plugin new engines/dummy -m my_template.rb
There are other useful variables available from within the template. You can see for yourself and play around by utilizing pry. Inside my template I added
require 'pry'; binding.pry
and then ran ls to show a list of available instance variables
ls -i
instance variables:
#_initializer #app_path #behavior #destination_stack #extra_entries #name #output_buffer #shell
#_invocations #args #builder #dummy_path #gem_filter #options #rails_template #source_paths
#after_bundle_callbacks #author #camelized #email #in_group #original_name #shebang
There's probably a more straightforward way, but this seems to work:
RAILS_ROOT.split('/').last
EDIT: Bleah - this got voted down once, and the voter was right. If I'd read the question more carefully, I'd have noticed the 2.3 and template.rb elements. Apologies.
I suspect that RAILS_ROOT won't have been created at the point that you need the app name. Looking at ruby\lib\ruby\gems\1.8\gems\rails-2.2.2\bin\rails, however, almost the first thing that happens is this:
app_path = ARGV.first
It's used at the end of the script to allow a chdir and freeze to be done if needed - I didn't know I could insta-freeze at creation, so I learned something new at least. ARGV then gets used here:
Rails::Generator::Scripts::Generate.new.run(ARGV, :generator => 'app')
which quickly gets us to the place where ARGV is really handled:
rails-2.3.1\lib\rails_generator\scripts.rb
where I see
Rails::Generator::Base.instance(options[:generator], args, options).command(options[:command]).invoke!
Somewhere below here is probably where the templating gets handled. I'm afraid I'm at a very early stage with 2.3 and templating is an area that I haven't looked at yet.
Does that help any better than my first effort?
RAILS_ROOT will give you the absolute path to your root directory. Your app name will be the portion of the string after the final '/' which you can grab in any number of ways.
EDIT: Not quite enough to get the job done. Mike and Dan iron it out below.
I believe the preferred way now is to call Rails.root and no longer RAILS_ROOT. Apparently someone on planet rails has an aversion to uppercase or some similar important reason. As of 2.3.5 they both appear to work.
I was getting error
`template': undefined local variable or method `app_name'
ruby 1.9.2p290, rails 3.2.11, thor 0.18.0, Windows
but with rails 2.3 generator:
class DynanavGenerator < Rails::Generators::Base
(can't be sure whether this error happened under rails 3.0.9 or earlier)
changed class definition to be:
class DynanavGenerator < Rails::Generators::NamedBase
which then gave:
No value provided for required arguments 'name'
I then added a 'name' ("something" below):
rails generate dynanav something --force
which gave the original error, so I then added:
def app_name
#name.titleize
end
to the class and all was well.
As of Rails 4 (maybe earlier versions?), use Rails.application.class to get the application name. For example, if your app is named Fizzbuzz, here are a few ways you might access it:
rails(development)> Rails.application.class
=> Fizzbuzz::Application
rails(development)> Rails.application.class.name
=> "Fizzbuzz::Application"
rails(development)> Rails.application.class.parent
=> Fizzbuzz
rails(development)> Rails.application.class.parent.to_s
=> "Fizzbuzz"

How to fix / debug 'expected x.rb to define X.rb' in Rails

I have seen this problem arise in many different circumstances and would like to get the best practices for fixing / debugging it on StackOverflow.
To use a real world example this occurred to me this morning:
expected announcement.rb to define Announcement
The class worked fine in development, testing and from a production console, but failed from in a production Mongrel. Here's the class:
class Announcement < ActiveRecord::Base
has_attachment :content_type => 'audio/mp3', :storage => :s3
end
The issue I would like addressed in the answers is not so much solving this specific problem, but how to properly debug to get Rails to give you a meaningful error as expected x.rb to define X.rb' is often a red herring...
Edit (3 great responses so far, each w/ a partial solution)
Debugging:
From Joe Van Dyk: Try accessing the model via a console on the environment / instance that is causing the error (in the case above: script/console production then type in 'Announcement'.
From Otto: Try setting a minimal plugin set via an initializer, eg: config.plugins = [ :exception_notification, :ssl_requirement, :all ] then re-enable one at a time.
Specific causes:
From Ian Terrell: if you're using attachment_fu make sure you have the correct image processor installed. attachment_fu will require it even if you aren't attaching an image.
From Otto: make sure you didn't name a model that conflicts with a built-in Rails class, eg: Request.
From Josh Lewis: make sure you don't have duplicated class or module names somewhere in your application (or Gem list).
That is a tricky one.
What generally works for me is to run "script/console production" on the production server, and type in:
Announcement
That will usually give you a better error message. But you said you already tried that?
I just ran into this error as well.
The short of it was that my rb file in my lib folder was not in a folder structure to match my module naming convention. This caused the ActiveSupport auto loader to use the wrong module to see if my class constant was defined.
Specifically I had defined the following class
module Foo
class Bar
end
end
In the root of /lib/bar.rb
This caused the autoloader to ask module Object if Bar was defined instead of module Foo.
Moving my rb file to /lib/foo/bar.rb fixed this problem.
I've encountered this before, and the AttachmentFu plugin was to blame. I believe in my case it was due to AttachmentFu expecting a different image processor than what was available, or non-supported versions were also installed. The problem was solved when I explicitly added :with => :rmagick (or similar -- I was using RMagick) to the has_attachment method call even for non-image attachments. Obviously, make sure that your production environment has all the right gems (or freeze them into your application) and supporting software (ImageMagick) installed. YMMV.
As for not getting Rails and AttachmentFu to suck up and hide the real error -- we fixed it before figuring it out completely.
Since this is still the top Google result, I thought I'd share what fixed the problem for me:
I had a module in the lib folder with the exact same name as my application. So, I had a conflict in module names, but I also had a conflict of folder names (not sure if the latter actually makes a difference though).
So, for the OP, make sure you don't have duplicated class or module names somewhere in your application (or Gem list).
For me, the cause was a circular dependency in my class definitions, and the problem only showed up using autotest in Rails. In my case, I didn't need the circular dependency, so I simply removed it.
You can try disabling all your plugins and add them back in one by one.
In environment.rb in the Initalizer section, add a line like this one:
config.plugins = [ :exception_notification, :ssl_requirement, :all ]
Start with the minimum set to run your application and add them in one by one. I usually get this error when I've defined a model that happens to map to an existing filename. For example, a Request model but Rails already has a request.rb that gets loaded first.
I had this problem for a while and in my case the error was always preceded from this S3 error:
(AWS::S3::Operation Aborted) "A
conflicting conditional operation is
currently in progress against this
resource. Please try again."
This problem usually occurs when creating the same bucket over and over again. (Source AWS Developers forum)
This was due to the fact that I had used attachment_fu to create the bucket and I had decommented the line containing the command Bucket.create(##bucket_name) in lib/technoweenie/attachment_fu/backends/s3_backends.rb (near to line 152).
Once commented or deleted the command Bucket.create(##bucket_name) the problem disappeared.
I hope this helps.
Changing class names while using STI caused this for me:
Class changed from 'EDBeneficiary' to 'EdBeneficiary'
Existing records had 'EDBeneficiary' stored in the 'type' column, so when Rails tried to load them up the exception was raised.
Fix: Run a migration to update values in the 'type' column to match the new class name.
in my case, I am getting this error in the development console but I can load the class in irb
Sorry this isn't a definitive answer, but another approach that might work in some specific circumstance:
I just ran in to this problem while debugging a site using Ruby 1.8.7 and Merb 1.0.15. It seemed that the class in question (let's call it SomeClass) was falling out of scope, but when some_class.rb file was automatically loaded, the other files it required (some_class/base.rb etc) were not loaded by the require mechanism. Possibly a bug in require?
If I required some_class file earlier, such as the end of environment.rb, it seems to prevent the object falling out of scope.
I was getting this error duo to a controller definition being in a file that wasn't named as a controller. For instance, you have a Comment model and you define the controller in a comment.rb file instead of comments_controller.rb
I had this problem with rails version 1.2.3. I could reproduce the problem only with mongrel, using console environment access didn't give any useful info. In my case, I solved making the RAILS_ROOT/html folder writable by mongrel and then restarting the web server, as some users reported here:
http://www.ruby-forum.com/topic/77708
When I upgraded rails from 1.1.6 to 1.2.6 and 2.0.5 for my app, I faced this error. In short, old plugins caused this error. These plugins were already out-dated and no update anymore (even no repo!). After I removed them, the app worked on 1.2.6 and 2.0.5. But I didn't check the detail source code of the plugins.

Resources