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.
Related
I have question about naming conventions and autoloading.
I want to have a presenter ItemPresenter in app/presenters/items/item_presenter.rb
My understanding was that I can just create that file like this:
module Items
class ItemPresenter
end
end
But when I do this and try to call the presenter as Items::ItemPresenter I get uninitialized constant error:
uninitialized constant Items::ItemPresenter
def show
#presenter = Items::ItemPresenter.new # this is the highlighted line of my Controller
EDIT: Rails, Custom Folders and Namespaces is not duplicate because it's about different dir structure jobs/smth.rb while I am trying to implement presenters/items/item_presenter.rb (1 more level)
EDIT2: neither it works from rails console: NameError: uninitialized constant Items::ItemPresenter
EDIT2: I tried doing this as suggested:
module Presenters
module Items
class ItemPresenter
def test
"hello"
end
end
end
end
And #presenter = Presenters::Items::ItemPresenter.new in my controller:
uninitialized constant TrialsController::Presenters
It seems like Rails do not see that directory at all.
EDIT3: Created a sample app https://github.com/dontlookforme/test_app
EDIT4: Figured it out. I screwed up the file name (see the answer I've posted)
I found the answer but it's necessary to see #user1556912's sample app (link in the original question) to see what happened.
The problem is that the filename is items_presenter.rb (plural) but the class name is ItemPresenter (singular).
As I pointed out in a comment on #Anthony E's answer, Rails will autoload everything in the /app dir, so it's not necessary explicitly to tell Rails about these files. However, along with namespaces matching dir hierarchies, the names of the classes must also match the names of the files exactly. In this case, I was able to get the class to load in the rails console by renaming items_presenter.rb to item_presenter.rb.
Going back to #Anthony E's answer, though, I do agree that the Items:: namespace seems superfluous here. I would just do app/presenters/item_presenter.rb.
app/presenters/ is the conventional path to store presenters. In fact, you can probably go without folder nesting for items:
app/presenters/item_presenter.rb
You'll need to update the module path accordingly:
module Presenters
class ItemPresenter
def test
"hello"
end
end
end
Then, you can tell Rails to automatically load this file in your application.rb:
config.autoload_paths << '#{config.root}/app/presenters'
Ugh. The thing I was doing wrong is the file name.
I named the preseter file items_presenter.rb but the class had singular Item in the name ItemPresenter.
Fixed that and everything started working.
Thanks for the help guys!
I'm having a problem with a module name and the folder structure.
I have a model defined as
module API
module RESTv2
class User
end
end
end
The folder structure looks like
models/api/restv2/user.rb
When trying to access the class, I get an uninitialized constant error. However, if I change the module name to REST and the folder to /rest, I don't get the error.
I assume the problem has to do with the naming of the folder, and I've tried all different combos of /rest_v_2, /rest_v2, /restv_2, etc.
Any suggestions?
Rails uses the 'underscore' method on a module or class name to try and figure out what file to load when it comes across a constant it doesn't know yet. When you run your module through this method, it doesn't seem to give the most intuitive result:
"RESTv2".underscore
# => "res_tv2"
I'm not sure why underscore makes this choice, but I bet renaming your module dir to the above would fix your issue (though I think I'd prefer just renaming it to "RestV2 or RESTV2 so the directory name is sane).
You'll need to configure Rails to autoload in the subdirectories of the app/model directory. Put this in your config/application.rb:
config.autoload_paths += Dir["#{config.root}/app/models/**/"]
Then you should be able to autoload those files.
Also, your likely filename will have to be app/model/api/res_tv2/user.rb, as Rails uses String.underscore to determine the filename. I'd just call it API::V2::User to avoid headaches, unless you have more than one type of API.
created a games_account.rb file in the library folder. The following is the structure
module GamesAccounts
class GamesAccountsClient
.
.
.
.
.
end
end
trying to do GamesAccounts::GamesAccountsClient.new in the controller gives me the error
uninitialized constant GamesController::GamesAccounts
I have even added
config.autoload_paths += %W(#{config.root}/lib) in the applications.rb
Am i doing anything wrong here?
I'm not sure about this, but I think you might need to put it in lib/games_accounts/games_accounts_client.rb instead of what you have now, which I presume is lib/games_account.rb. The idea is it should be lib/<module name>/<class name>.rb.
The problem is in your file, name it games_accounts.rb instead of games_account.rb and it should work (because it will match the module name).
If you plan to put many classes within this module, create a directory named games_accounts, and add the class there with the mapping of each file to each class, and put it on your application.rb file, like
config.autoload_paths += %W(#{config.root}/lib/games_accounts)
I have a other thought, If your file is something which is be helping the models than try having it in the form of concerns folder and adding your file there. Since Rails 4 onwards all these support activities will be taken by concerns it's good to adopt right away. Have a read at the blog post by DHH also:
http://37signals.com/svn/posts/3372-put-chubby-models-on-a-diet-with-concerns
This is an evolving issue related to a previous posting I made...
I am playing around some - to try to learn how the /lib/ directory in Rails works - and how to reference variables defined in the /lib/ directory for use in a view.
I have a file called helloworld.rb and it's saved in a /lib/hellotest/ directory in Rails.
The helloworld.rb file has the following code:
module HelloWorld
def hello
#howdy = "Hello World!"
end
end
I want to be able to display the results of this method on a view called index.html.erb, so I include the following code in the index_helper.erb file:
module IndexHelper
require 'helloworld'
end
I have learned that I need to include the following line of code in the /config/application.rb file:
config.autoload_paths += %W(#{Rails.root}/lib/hellotest/)
Also, I include the following code on the view index.html.erb:
<%= #howdy %>
I think I may have found something that is causing problems. I didn't want to load the entire /lib/ directory at startup so I put the file in a subdirectory called /lib/hellotest/. I've read there are some issues with how Rails interprets module/class naming conventions in the lib folder, but I can't quite figure it out. I see a good resource regarding this possible solution to my problem on William B Harding's Blog, on point 2 - but I can't quite get my arms around this solution as it pertains to my problem.
Any advice please?
What am I missing?
I'd suggest that unless you have a good reason to do otherwise, follow the conventional naming for modules and classes (as described in the link you provided). Rename helloworld.rb to hello_world.rb, move it into lib, and change your autoload_paths to:
config.autoload_paths += %W(#{Rails.root}/lib/)
Finally, change require 'hello_world' to require 'hello_world' in your IndexHelper module. It should then load normally.
tl;dr
What's a simple way I can create a view helpers module I can use in many apps?
What file, located where, loaded how?
I'm on Rails 2.3.11.
I have a bunch of view helper methods. Here's an example of one of them:
# Render form input fields to add or edit a ZIP code.
def render_zip_code_fields( model_instance )
# Bla bla bla ...
end
I have about 20 or so that I've developed over the years and often use in various applications. I'd like to wrap them all up in one file that I can just drop into and app and then be able to call them in my views.
Why not just copy-and-paste them into application_helper.rb? That just doesn't feel right to me. It seems like it should be a separate file.
In fact I tried creating in /lib...
# /lib/my_view_helpers.rb
module MyViewHelpers
# ...
end
And then in application_helper.rb I put...
include MyViewHelpers
But I got a lot of "uninitialized constant MyViewHelpers errors. Maybe a syntax error? I don't think I need to require my_view_helpers.rb first because it's in /lib. Everything in there gets loaded automatically, right?
So what's the right way to do this optimizing for simplicity?
Sorry this is so long. I get verbose when I'm tired.
As of Rails 3, /lib is no longer on the default load path. You will need to put the following line in the Application class in config/application.rb.
config.autoload_paths += ["#{config.root}/lib"]
An alternative would be to drop the file in app/helpers since it is a helper, after all.