Paperclip Rspec tests : why missing attr_accessor? - ruby-on-rails-3

I had a set of Rspec User Model tests that were passing, until I had the paperclip attribute "profile picture".
Everything is fine with paperclip, it works great, but I would like my tests also to be updated to pass. I just added this line to the #attr of the user_spec file:
:avatar => File.new (Rails.root + "public/images/Default_profile_picture.jpg")
in a before_each loop that creates a standard set of working attribute for the user model.
When I run the tests, ALL the tests give me the error message:
User model missing required attr_accessor for 'avatar_file_name' ...
Putting paperclip's fields as attr_accessor in the model makes the problem disappear in the test, but I don't think I should do this in my model (it does not work properly if I do).
Does anyone has an idea why I got these error messages when testing ? ... (I included the config line Shoulda::Matchers and the require paperclip lines in the spec/helper)
Thanks for any answer you may post !

It was simply that I forgot to run
rake db:test:prepare
before running my tests :-/

Related

Getting uninitialized constant (NameError) inside decorators when running rspec tests via rake

In my app I use an engine (blogit) to which I want to add some changes / behaviours.
I followed the guides on how to override engine controllers/models and added the following:
The Code
In config/initializer/blogit.rb
# Requires extension ruby files in lib/blogit.
Dir[Rails.root.join("lib/blogit/*.rb")].each {|f| require f}
In lib/blogit/engine.rb
module Blogit
class Engine < ::Rails::Engine
isolate_namespace Blogit
config.to_prepare do
Dir.glob(Rails.root + "app/decorators/**/blogit/*_decorator*.rb").each do |c|
require_dependency(c)
end
end
end
end
In app/decorators/controllers/blogit/comments_controller_decorator.rb
Blogit::CommentsController.class_eval do
def create
Rails.logger.info "decorated controller action"
# ... overridden stripped ...
end
end
In app/decorators/models/blogit/comment_decorator.rb
Blogit::Comment.class_eval do
belongs_to :user
end
To be mentioned:
I have also created a migration to add a user reference to the comments model, since my app uses devise and I only want logged_in users to be able to comment. (Therefore I don't need the standard behaviour, so I'm going to override it.)
The Problem
If I run rake I get the weird error:
/Users/Kassi/.rvm/rubies/ruby-1.9.3-p392-railsexpress/bin/ruby -S rspec ./spec/controllers/home_controller_spec.rb ./spec/models/user_spec.rb
/Users/Kassi/demo/app/decorators/controllers/blogit/comments_controller_decorator.rb:3:in `<top (required)>': uninitialized constant Blogit::CommentsController (NameError)
However, if I run the first line that rake mentions by hand (.../ruby -S ...), all tests are being run successfully.
In my project I'm using guard with spork. Running guard will also let the tests pass without any error.
The app itself runs fine, i.e. it starts without errors and I'm able to comment as I want. My decorator action code is being executed.
So what's different when running rake?
Why does it break?
Note:
Adding require "blogit" or require "blogit/comments_controller" doesn't help. It actually can't find the controller using require.
A Demo Application
Since this problem is part of a bigger project, I created a new app from scratch for testing purposes that contains only the relevant stuff: basic rails app, rspec, devise, blogit and the decorators.
It can be found here: https://github.com/kassi/decorator_demo_rspec (git://github.com/kassi/decorator_demo_rspec.git)
Another repo using testunit (which is working!) can be found here: https://github.com/kassi/decorator_demo_testunit (git://github.com/kassi/decorator_demo_testunit.git)
Instead of performing the require statements yourself, you can try activesupport-decorators that does it for you.

Setting default_url_options in test environment doesn't seem to work

I've put the following code into my config/environments/test.rb file:
config.action_mailer.default_url_options = { :host => "localhost:3000" }
however when I run my tests, all routes use http://test.host. I'm trying to work with an API that won't accept http://test.host as a valid callback URI, so I need to change this to properly receive the API response. Any idea why this isn't working? (I'm using RSpec, Guard, and Spork in my testing suite).
EDIT: Possibly relevant - this is being done inside of a controller spec.
EDIT2: It seems that it changes after a request is made via get, post, etc. Running the following code within the test:
Rails.logger.debug users_url
get 'http://google.com'
Rails.logger.debug users_url
would produce the following output:
http://localhost:3000/users
...get request related response here
http://google.com/users
Nowadays you can just set them in your test.rb like so:
Rails.application.routes.default_url_options[:host]= 'localhost:3000'
Rails.application.routes.default_url_options[:host]= 'localhost:3000'
In the developemnt.rb / test.rb, can be more concise as following:
Rails.application.configure do
# ... other config ...
routes.default_url_options[:host] = 'localhost:3000'
end
From my experience, url_options will not be passed into tests without a bit of hacking.
See e.g.
How to set locale default_url_options for functional tests (Rails)
http://www.ruby-forum.com/topic/3448797
I've frequently encountered this problem when trying to set the locale in tests. I've never used action mailer, though, so there may be a simpler way to do it.
The solution I've found for setting the default locale in url_options is just to patch actiondispatch and force it to use whatever locale I want it to. You could adapt this to your case this way:
class ActionDispatch::Routing::RouteSet
def url_for_with_default_url_options(options)
url_for_without_default_url_options(options.merge(:host => "localhost:3000" ))
end
alias_method_chain :url_for, :default_url_options
end
I put that code in a file in spec/support so it is used in rspec tests and I also require it from my env.rb file so I can use it in cucumber tests as well.
Keep in mind that this will patch it everywhere, in both test code and in actual code running under tests, and it will override any other settings for the :host key that you try to pass in (since the patch merges the fix on top of the options passed into url_for). In your case I believe that shouldn't be a problem.
Monkey patching is not a very elegant solution, though, and I used this after everything else failed. You might find a simpler solution specific to action mailer.
How are you running your tests? Maybe appending RAILS_ENV=test might help.

Rails, A method to be called only in production

I remember seeing this somewhere online but I know have trouble finding information about it. In Rails 3.1, I have a method at the beginning of a session controller, force_ssl, I only want it called in a production environment, how do I do that?
To clarify, the code looks something like this
class SessionsController < ApplicationController
force_ssl
end
I had a similar problem. force_ssl caused problems by testing with capybara and selenium. This here solved my problems and the tests are now running:
force_ssl if Rails.env.production?
I am using the line above in some Controllers. For example in the SessionController and UserController.
Rails.env.production? returns true if the current environment is 'production'. More generally, Rails.env.somestring? returns true if Rails.env == "somestring". From there you should be good.
** EDIT **
Well actually, there's an easier way to use ssl only in production. Check out this article

Failure in Rails Tutorial (Hartl) -section 7 - "unkown attribute: password"

I've searched this issue on the forum and have used a solution on the spork site to remove "--drb" from spec options, got it to load and run and still this persistent error keeps popping up. I've also run it without spork. I've read ahead on a bunch of rspec info and as stated dug through spork info, but nothing yet. I've also ran checks for typos, indentation, encoding... and am at a loss still. Other issues, I've been able to fix, but this one's got me. Here it is below if anyone has a suggestion:
Failures:
1) User password encryption has_password? method should be false if the passwords don't match
Failure/Error: #user = User.create!(#attr)
ActiveRecord::UnknownAttributeError:
unknown attribute: password
# ./spec/models/user_spec.rb:94:in `block (3 levels) in '
Finished in 0.836 seconds
1 example, 1 failure
<-- Slave(1) run done!
are you certain you have added :password as a virtual attribute on your User model? It's easy to miss but you need to include the line
attr_accessor :password
It's possible that this has changed between the time the question was asked (2011) and now, but I initially ran into the same issue -- I'd added all of the tests for password etc, and the User initialization itself was failing across the board with "unknown attribute: password".
On the face of it, GrahamJRoy's answer (and more importantly, subsequent comment of elaboration) addressed my confusion perfectly.
However, I then kept reading the next section of the tutorial and learned that the following line in the User model implies the same thing:
has_secure_password
Once I added this, I no longer needed the explicit attr_accessor declaration:
attr_accessor :password, :password_confirmation
My only complaint with the tutorial here is that Michael doesn't warn you that ALL of your User references will begin to fail if you add the :password and :password_confirmation to User.new() when the tutorial first shows you the updated constructor. I was expecting only the new tests to fail, thought I was off-track, and so searched elsewhere (such as here) for a solution before continuing the tutorial.
Make sure to change attr_accessible to attr_accessor in models/user.rb
I made the same mistake and overlooked it.

Rails sitemap generator, undefined method post_path?

I am using the following gem:
https://github.com/kjvarga/sitemap_generator
I have a posts model and have used post_path(post) in other parts of the application as it is based on Enki.
However in the sitemap file:
Post.all.each do |post|
sitemap.add post_path(post), :lastmod => post.updated_at
end
This returns the error when running the rake task rake sitemap:refresh:
rake aborted!
undefined method `post_path' for #<SitemapGenerator::Interpreter:0x279efd0>
And:
Post.all.each do |post|
sitemap.add posts_path(post), :lastmod => post.updated_at
end
Returns no errors. Can anyone shed any light on this or do I need to provide more of the code?
sitemap_generator actually includes all the helper methods in the create block, so you should be able to access posts_path.
I had a similar problem, and my answer also made me feel stupid. I was storing sitemap.rb in config/initializers, when it should be stored in the config/ directory. That meant it was running on startup and failing because the url helpers weren't properly loaded (and, incidentally, when I called rake sitemap:refresh, the sitemap was being generated twice - once in the initializer and again as the rake task!)
I feel a bit stupid on this one, it was simply because post_path was a helper and not accessible, so I simply had to move it into the method directly.