How can I stub private/protected methods to be passed in functional controller tests?
Having the following code for example:
app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
def create
#user = User.from_omniauth(auth_hash)
reset_session
session[:user_nickname] = #user.nickname
if #user.email.blank?
redirect_to edit_user_path(#user.nickname), :alert => "Please enter your email address."
else
redirect_to show_user_path(#user.nickname), :notice => 'Signed in!'
end
end
private
def auth_hash
request.env['omniauth.auth']
end
end
I tried the following :
test/controllers/sessions_controller_unit_test.rb
require 'test_helper'
class SessionsControllerTest < ActionController::TestCase
test "should create new user" do
# get the same 'request.env['omniauth.auth'] hash
auth_h = OmniAuth.config.mock_auth[:github]
# but auth_hash is never passed in User.find_or_create_from_auth_hash(auth_hash)
# method, which result to be nil breaking the User model call
get :create, provider: 'github', nickname: 'willishake', auth_hash: auth_h
assert_redirected_to show_user_path(nickname: 'willishake')
assert_equal session[:user_id], "willishake"
end
end
but when get :create (the test method) calls
the model User.find_or_create_from_auth_hash(auth_hash), auth_hash is nil, breaking the functional test.
So what's the right way to stub auth_hash private method and passing to User model call User.from_omniauth(auth_hash) ?
UPDATE:
after blowmage suggestion, it works like the following:
require 'test_helper'
class SessionsControllerTest < ActionController::TestCase
def setup
request.env['omniauth.auth'] = OmniAuth.config.mock_auth[:github]
end
test "should create new user" do
get :create, provider: 'github', nickname: 'willishake'
assert_equal session[:user_id], "willishake"
assert_redirected_to show_user_path(nickname: 'willishake')
end
end
Try this:
# set the request.env['omniauth.auth'] hash
auth_h = OmniAuth.config.mock_auth[:github]
request.env['omniauth.auth'] = auth_h
Related
Under the commands folder, I'd like to initialize a controller
but Sinatra reports this error in the logs
ArgumentError: wrong number of arguments (given 1, expected 2)
/home/daniel/sinatraApi/app/commands/authenticate_user.rb:6:in `initialize'
/home/daniel/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:86:in `new'
2.0.7/lib/rack/builder.rb:147:in `to_app'
config.ru:15:in `inner_app'
/
The controllers are called
use AuthenticateUser
run ApplicationController
I've tried to add
use Commands::AuthenticateUser
or require
require "./app/commands/authenticate_user"
on config.ru
Authenticate_user
require 'jwt'
#require './app/controllers/application'
class AuthenticateUser
prepend SimpleCommand
def initialize(email, password)
#email = email
#password = password
end
def call
JsonWebToken.encode(user_id: user.id) if user
end
private
attr_accessor :email, :password
def user
user = User.find_by_email(email)
return user if user && user.authenticate(password)
errors.add :user_authentication, 'invalid credentials'
nil
end
end
How can I setup the namespace or nested controllers in Sinatra?
i have been learning rails through
http://guides.rubyonrails.org/getting_started.html.
I came across a error while performing save data in controller. The error that comes up when running the blog is :-undefined method `title' for nil:NilClass
**
My code for posts_controller.rb is
**
class PostsController < ApplicationController
def new
end
def create
#post=Post.new(params[:post].permit(:title,:text))
#post.save
redirect_to #post
end
private
def post_params
params.require(:post).permit(:title,:text)
end
def show
#post=Post.find(params[:id])
end
end
**
My code for show.html.rb is
**
<p>
<strong> Title:</strong>
<%= #post.title %>
</p>
<p>
<strong> Text:</strong>
<%= #post.text %>
</p>
**
The code for create_posts.rb
**
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :text
t.timestamps
end
end
Please help me out why this error is coming up when I have defined title in create_posts.
All methods defined after private are accessible only internally. Move the show method above private. And make sure you have a file called app/views/posts/show.html.erb and not .rb
Good luck!
# Make sure that you trying to access show method before the declaration of private as we can't access private methods outside of the class.
def show
#post = Post.find(params[:id])
end
def index
#posts = Post.all
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :text))
redirect_to #post
else
render 'edit'
end
end
private
def post_params
params.require(:post).permit(:title, :text)
end
end
//vKj
I and new to ruby and rails; I have the below ruby class definition that I am using in my rails 3 app. This class is simply used as a property container for contact information populated in my view on submit (form_for). I read a post where you can use ActiveModel directly apart from ActiveRecord, to perform validation, so I am trying it. I am getting the following exception when I check to see if the the object is valid? in my controller on postback. I assumed that valid? would be available being that I included ActiveModel::Validations; perhaps I am doing a few other things a$$ backwards. Any help would be appreciated:
undefined method `valid?' for #
Here's my class definition, further down is how I am handling it in my controller action:
require 'active_model'
class ContactModel
extend ActiveModel::Naming
include ActiveModel::AttributeMethods
include ActiveModel::Validations
include ActiveModel::Conversion
validates_presence_of :first_name, :last_name, :email_address, :email_address_confirmed, :subject, :contact_message
attr_accessor :first_name, :last_name, :email_address, :email_address_confirmed,
:telephone_number, :subject, :contact_message
Just messing around testing.
validates_each :first_name, :last_name do |record, attr, value|
record.errors.add attr, 'starts with z.' if value.to_s[0] == z
end
...
end
In my controller/action...
def send_email
##contact_model = ContactModel.new().initialize_copy(params[:contact_model])
#contact_model = params[:contact_model].dup
respond_to do |format|
if (#contact_model.valid?)
# Tell the UserMailer to send a welcome Email after save
ContactMailer.contact_email(#contact_model).deliver
format.html { redirect_to(#contact_model, notice: 'Email successfully sent.') }
format.json { render json: #contact_model, status: :created, location: #contact_model }
else
# What to do here?
end
end
end
In your controller you are setting #contact_model to a hash, params[:contact_model], and then calling valid? on it. You need create an instance of ContactModel and call valid on that. Like so:
#contact_model = ContactModel.new(params[:contact_model])
if (#contact_model.valid?)
...
I see commented out code that calls ContactModel.new(), but that's not how you want to do it anyway. Also, there is no reason to dup() or initialize_copy() on the params stuff.
I am not able to create new api_user. Everytime I try to create it I get
Can't mass-assign protected attributes: utf8, authenticity_token, api_user, commit, action, controller
here's my model api_user.rb
class ApiUser < ActiveRecord::Base
attr_accessible :api_key, :count, :email, :name, :organization
end
controller api_users_controller.rb
class ApiUsersController < ApplicationController
#skip_before_filter :verify_authenticity_token
def new
#api_user = ApiUser.new
end
def create
#api_user=ApiUser.create(params)
render :text=>"#{#api_user.id}"
end
def destroy
#api_user=ApiUser.find(params[:id])
#api_user.destroy
render :text=>"Deleted successfully"
end
end
I am using Ruby 1.9.2 and Rails 3.2.3
In order to create the ApiUser, you should use only the correct params:
#api_user=ApiUser.create(params[:api_user])
not all the paramshash
I have following controller:
class CarsController < ApplicationController
autocomplete :user, :name
before_filter :require_user, :except => [:my_action]
def index
end
...
def my_action
end
end
I want to allow to see all actions in this controller only for log in users - this works me fine. But the action my_action I would like to have accesible for everyone - also for a people who are not log in.
I tried to set :before_filter with the :except parameter, also with the :only parameter, but nothing works me... The app always want for me to be log in... what I am doing still wrong?
EDIT: require_user from application_controller.rb:
def require_no_user
logger.debug "ApplicationController::require_no_user"
if current_user
#store_location
flash[:warning] = "You must be logged out to access this page"
redirect_to account_url
return false
end
end
Use
skip_before_filter :require_user, :only => [:my_action]