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 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.
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.
Hello I've been looking around at all the various tutorials out there for Paperclip post processing but somehow I can not get the 'Make' method to invoke.
Take a look at line 36 here... http://pastie.org/private/epfgcxywhyh4wpmozypg
It uploads normally without any errors or warnings but I can never see the puts statement in the make method which tells me that this isn't being invoked.
EDIT
I can run this in the model without a problem and I get True,
def class_exists?(class_name)
klass = Paperclip.const_get(class_name)
return klass.is_a?(Class)
rescue NameError
return false
end
Any ideas?
Two days ago I was facing the same problem. Here what I did to make it work:
Go to the command prompt and type: "which convert" command. This is ImageMagick command so if it says /usr/bin/convert then try adding
Paperclip.options[:command_path] = "/usr/bin"
in your config/environments/development.rb. Remove /convert from what you get over there.
then change name of your file file_contents.rb to paperclip_postprocess.rb and put it into directory: RAILS_ROOT/config/initializers/paperclip_postprocess.rb
You can cross check if your attachment is being processed or not by adding following lines in your model:
before_post_process :before_post_process
after_post_process :after_post_process
def before_post_process
puts "===========Before processing attachment==========="
end
def after_post_process
puts "-----------After processign attachment------------"
end
Take a look here
It worked for me at least.
I noticed this line in the Paperclip README:
NOTE: Because processors operate by turning the original attachment into the styles, no processors will be run if there are no styles defined.
And looking at your paste, you define everything but a :style argument, so maybe that's the problem?
We recently had a problem where, after a series of commits had occurred, a backend process failed to run. Now, we were good little boys and girls and ran rake test after every check-in but, due to some oddities in Rails' library loading, it only occurred when we ran it directly from Mongrel in production mode.
I tracked the bug down and it was due to a new Rails gem overwriting a method in the String class in a way that broke one narrow use in the runtime Rails code.
Anyway, long story short, is there a way, at runtime, to ask Ruby where a method has been defined? Something like whereami( :foo ) that returns /path/to/some/file.rb line #45? In this case, telling me that it was defined in class String would be unhelpful, because it was overloaded by some library.
I cannot guarantee the source lives in my project, so grepping for 'def foo' won't necessarily give me what I need, not to mention if I have many def foo's, sometimes I don't know until runtime which one I may be using.
This is really late, but here's how you can find where a method is defined:
http://gist.github.com/76951
# How to find out where a method comes from.
# Learned this from Dave Thomas while teaching Advanced Ruby Studio
# Makes the case for separating method definitions into
# modules, especially when enhancing built-in classes.
module Perpetrator
def crime
end
end
class Fixnum
include Perpetrator
end
p 2.method(:crime) # The "2" here is an instance of Fixnum.
#<Method: Fixnum(Perpetrator)#crime>
If you're on Ruby 1.9+, you can use source_location
require 'csv'
p CSV.new('string').method(:flock)
# => #<Method: CSV#flock>
CSV.new('string').method(:flock).source_location
# => ["/path/to/ruby/1.9.2-p290/lib/ruby/1.9.1/forwardable.rb", 180]
Note that this won't work on everything, like native compiled code. The Method class has some neat functions, too, like Method#owner which returns the file where the method is defined.
EDIT: Also see the __file__ and __line__ and notes for REE in the other answer, they're handy too. -- wg
You can actually go a bit further than the solution above. For Ruby 1.8 Enterprise Edition, there is the __file__ and __line__ methods on Method instances:
require 'rubygems'
require 'activesupport'
m = 2.days.method(:ago)
# => #<Method: Fixnum(ActiveSupport::CoreExtensions::Numeric::Time)#ago>
m.__file__
# => "/Users/james/.rvm/gems/ree-1.8.7-2010.01/gems/activesupport-2.3.8/lib/active_support/core_ext/numeric/time.rb"
m.__line__
# => 64
For Ruby 1.9 and beyond, there is source_location (thanks Jonathan!):
require 'active_support/all'
m = 2.days.method(:ago)
# => #<Method: Fixnum(Numeric)#ago> # comes from the Numeric module
m.source_location # show file and line
# => ["/var/lib/gems/1.9.1/gems/activesupport-3.0.6/.../numeric/time.rb", 63]
I'm coming late to this thread, and am surprised that nobody mentioned Method#owner.
class A; def hello; puts "hello"; end end
class B < A; end
b = B.new
b.method(:hello).owner
=> A
Copying my answer from a newer similar question that adds new information to this problem.
Ruby 1.9 has method called 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)
This has been backported to 1.8.7 by this gem:
ruby18_source_location
So you can request for the method:
m = Foo::Bar.method(:create)
And then ask for the source_location of that method:
m.source_location
This will return an array with filename and line number.
E.g for ActiveRecord::Base#validates this returns:
ActiveRecord::Base.method(:validates).source_location
# => ["/Users/laas/.rvm/gems/ruby-1.9.2-p0#arveaurik/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]
For classes and modules, Ruby does not offer built in support, but there is an excellent Gist out there that builds upon source_location to return file for a given method or first file for a class if no method was specified:
ruby where_is module
In action:
where_is(ActiveRecord::Base, :validates)
# => ["/Users/laas/.rvm/gems/ruby-1.9.2-p0#arveaurik/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]
On Macs with TextMate installed, this also pops up the editor at the specified location.
Maybe the #source_location can help to find where is the method come from.
ex:
ModelName.method(:has_one).source_location
Return
[project_path/vendor/ruby/version_number/gems/activerecord-number/lib/active_record/associations.rb", line_number_of_where_method_is]
OR
ModelName.new.method(:valid?).source_location
Return
[project_path/vendor/ruby/version_number/gems/activerecord-number/lib/active_record/validations.rb", line_number_of_where_method_is]
This may help but you would have to code it yourself. Pasted from the blog:
Ruby provides a method_added()
callback that is invoked every time a
method is added or redefined within a
class. It’s part of the Module class,
and every Class is a Module. There are
also two related callbacks called
method_removed() and
method_undefined().
http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby
If you can crash the method, you'll get a backtrace which will tell you exactly where it is.
Unfortunately, if you can't crash it then you can't find out where it has been defined. If you attempt to monkey with the method by overwriting it or overriding it, then any crash will come from your overwritten or overridden method, and it won't be any use.
Useful ways of crashing methods:
Pass nil where it forbids it - a lot of the time the method will raise an ArgumentError or the ever-present NoMethodError on a nil class.
If you have inside knowledge of the method, and you know that the method in turn calls some other method, then you can overrwrite the other method, and raise inside that.
Very late answer :) But earlier answers did not help me
set_trace_func proc{ |event, file, line, id, binding, classname|
printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}
# call your method
set_trace_func nil
You might be able to do something like this:
foo_finder.rb:
class String
def String.method_added(name)
if (name==:foo)
puts "defining #{name} in:\n\t"
puts caller.join("\n\t")
end
end
end
Then ensure foo_finder is loaded first with something like
ruby -r foo_finder.rb railsapp
(I've only messed with rails, so I don't know exactly, but I imagine there's a way to start it sort of like this.)
This will show you all the re-definitions of String#foo. With a little meta-programming, you could generalize it for whatever function you want. But it does need to be loaded BEFORE the file that actually does the re-definition.
You can always get a backtrace of where you are by using caller().