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.
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.
Pretty self explanatory.
I use array_name.first to get the first element. How do you extend it to get second, third, random, etc?
Thanks.
In Ruby you can just reopen any existing class and add your own functions.
In rails, you already have those methods defined in activesupport
See the source at github: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/array/access.rb
I discovered it is already there, in Ruby 1.9.2 at least.
If it weren't there, I would create a file in config/initializers called array_helper.rb (or whatever) and add the following code:
class Array
def second
self[1]
end
end
Why? Because all classes in Ruby are open and you can extend anything you want.
Here's some tricks to know:
When working in the console, if you want to test the file, be sure to use rails console and not irb. Also, do reload! after creating or updating the above file. Finally, all objects must be recreated to use the new code after reload!.
I am using the acts_as_taggable_on gem and would like to add a method to one of the gem source files (tag.rb), but I do not want to change the gem source in any way.
I have tried creating my own tag.rb file to in the /app/models directory or in the /lib directory, and then adding the desired method to that file expecting that ruby will merge the two tag.rb files
But when I do I get a NoMethodError: undefined method ...
What am I missing?
I think you're right that reopening the Tag class is the way to go. I wouldn't introduce another level of inheritance unless it really made sense for your code.
I'm not sure, off the top of my head, why reopening the Tag class didn't work. A few thoughts:
1 - When you wrote your own Tag class, did it descend from ActiveRecord::Base? The Tag class in acts as taggable on does, and I could see how neglecting that might mess things up.
2 - If I needed a place to put code that reopened a plugin class for a single method, I'd probably put it in an initializer file (such as config/initializers/tag_patch.rb). Just to keep things clean.
3 - If all else fails and you still can't get the Tag class reopened properly (for whatever reason) there are other metaprogramming techniques you might try to add the method. For example:
Tag.send(:define_method, “method_name”) do
#code for your method
end
Wait, you shouldn't be adding method to the file, but to the class instead. Are you familiar with the concept of reopening the class? You can't add a method just by naming your file same as the one which original class is defined in. Fortunately. :)
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.