Strong parameters with Rails 4.0 and Devise - ruby-on-rails-4

I am using Rails 4.2 and devise.Request type will always be JSON.My registrations controller looks like this
class Users::RegistrationsController < Devise::RegistrationsController
before_filter :configure_sign_up_params, only: [:create]
def create
if request.format(request) == "application/json"
build_resource(sign_up_params)
if resource.save
render :json => {:success => "true", :message => "Thank You For Registering."}
else
render :json => {:success => "false", :message => resource.errors.full_messages}
end
else
super
end
end
protected
def configure_sign_up_params
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:email, :password, :password_confirmation)
end
end
end
The parameters that show-up in the console is like :
Parameters: {"email"=>"test123#gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "registration"=>{"email"=>"test123#gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}
The error it produces is that the controller doesn't recognize the email and password fields and always returns error like :
["Email can't be blank","Password can't be blank"]
Does this happen because of any foolishness that I have written in the code?Please help

Your configure_sign_up_params method has to be something like this to work.
def configure_sign_up_params
devise_parameter_sanitizer.for(:registration) do |u|
u.permit(:email, :password, :password_confirmation)
end
end
If you can see the console content what you have posted, it contains a hash with registration as a key:
"registration"=>{"email"=>"test123#gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}

Related

Testing custom devise session controller using RSpec

I'm using a custom Devise SessionsController:
#custom_sessions_controller.rb
class CustomSessionsController < Devise::SessionsController
end
In my routes.rb devise is set up like this:
#routes.rb
devise_for :custom_users, {
:singular => 'custom_user',
:class_name => 'CustomUser',
:path => "/",
:path_names => { :sign_in => 'login', :sign_out => 'logout' },
:controllers => { :sessions => "custom_sessions" }
}
I would like to write a simple rspec test:
#custom_sessions_controller_spec.rb
require 'rails_helper'
describe CustomSessionsController, :type => :controller do
describe "login" do
before do
setup_controller_for_warden
#request.env["devise.mapping"] = Devise.mappings[:custom_user]
#my_user = FactoryGirl.create(:custom_user) # creates user with valid credentials
end
it "should succeed with valid credentials" do
sign_in #my_user
curr_user = assigns(:current_custom_user)
expect(curr_user).to eq(#my_user)
expect(response).to be_success
end
end
end
In my rails_helper.rb the following lines are present:
require 'devise'
...
RSpec.configure do |config|
...
config.include Devise::TestHelpers, :type => :controller
config.include Warden::Test::Helpers , :type => :controller
...
The problem is that curr_user in the test is alway nil. What am I doing wrong? Or how to test a custom devise session controller? Or how to log in in - other - tests using a custom devise session?
instead of:
describe CustomSessionsController, :type => :controller do
try:
RSpec.describe CustomSessionsController, :type => :controller do
Hope it works!
Using
#controller.current_custom_user
instead of
assigns(:current_custom_user)
seems to work.

Carrierwave + ActiveAdmin with example for file and image field. results in "stack level too deep"

I am attempting to create a file and image field on ActiveAdmin. Example.
What I have so far.
Created a Migration to add file and image columns to the database.
Created Active Admin and edited display form.
Created the model
Created 2 uploaders
My code results in "stack level too deep" error.
The weird thing is the code is exactly the same as my example which works fine.
admin/product.rb
ActiveAdmin.register Product do
permit_params :title, :image, :file
form(:html => { :multipart => true }) do |f|
f.inputs "Create Product..." do
f.input :title
f.input :image, :as => :file, :hint => f.template.image_tag(f.object.image.url(:thumb))
f.input :file, :as => :file
end
f.actions
end
end
models/product.rb
class Product < ActiveRecord::Base
mount_uploader :file, FileProductsUploader
mount_uploader :image, ImageProductsUploader
end
uploaders/file_products_uploader.rb
class FileProductsUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"#{Rails.root}/public/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
uploaders/image_products_uploader.rb
class ImageProductsUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :file
def store_dir
"#{Rails.root}/public/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process :resize_to_fit => [250, 250]
end
end
Error Message
SystemStackError in Admin::ProductsController#update
stack level too deep
{"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"ViiAmqH+S9XjP0wBSc7I2USEl1LXLw/N532Kd+uhNqc=",
"product"=>{"title"=>"First Product",
"image"=>#<ActionDispatch::Http::UploadedFile:0x50e6008 #tempfile=# <Tempfile:C:/Users/User/AppData/Local/Temp/RackMultipart20141016-7388-e5v6is>,
#original_filename="example.png",
#content_type="image/png",
#headers="Content-Disposition: form-data; name=\"product[image]\"; filename=\"example.png\"\r\nContent-Type: image/png\r\n">},
"commit"=>"Update Product",
"id"=>"1"}
Console Error message
Unpermitted parameters: utf8, _method, authenticity_token, commit, id
Completed 500 Internal Server Error in 138ms
SystemStackError (stack level too deep):
actionpack (4.1.5) lib/action_dispatch/middleware/reloader.rb:79
None of the online solutions worked for me. I solved the error changing the local temp directory
Uploader/*
def cache_dir
# should return path to cache dir
Rails.root.join 'tmp/uploads'
end

ActiveModel::ForbiddenAttributesError in Devise::RegistrationsController#create

I am getting this
ActiveModel::ForbiddenAttributesError in Devise::RegistrationsController#create
error when i used devise gem
error in console is
Parameters: {"utf8"=>"✓", "authenticity_token"=>"kwJU2b47XvXj9hNV1HAdttW/rvetDepAVCn+jPvndy8=", "user"=>{"email"=>"nagarajureddy#gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
Completed 500 Internal Server Error in 1ms
ActiveModel::ForbiddenAttributesError (ActiveModel::ForbiddenAttributesError): activemodel (4.1.0) lib/active_model/forbidden_attributes_protection.rb:21:in `sanitize_for_mass_assignment'
Please any one help me
Add this in your application controller and restart the server, It's because of Strong Parameters in Rails4.
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:email, :password, password_confirmation) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:email, :password, password_confirmation) }
end

Mongoid Model won't persist has_one via embeds_one relation

I'm having trouble with embeds in a mongoid4-based rails 4 app. I've been looking for an answer everywhere for the past 2 days. So here is the code.
This is a church management app, with a Service model, embedding a team and a band. Each team/band has several roles such as "presidence", "communion" that refer to a user.
My models :
class Service
include Mongoid::Document
...
embeds_one :team, autobuild: true
embeds_one :band, autobuild: true
...
accepts_nested_attributes_for :team, :band
end
class Team
include Mongoid::Document
embedded_in :service
has_one :presidence, :class_name => 'User', autosave: true
has_one :message, :class_name => 'User', autosave: true
...
end
class Band
include Mongoid::Document
has_one :lead, :class_name => 'User', autosave: true
has_one :guitar, :class_name => 'User', autosave: true
...
embedded_in :service
end
class User
include Mongoid::Document
embeds_one :profile
belongs_to :team, :inverse_of => :presidence
belongs_to :team, :inverse_of => :message
belongs_to :band, :inverse_of => :lead
belongs_to :band, :inverse_of => :guitar
def fullname
"#{profile.firstname} #{profile.lastname}"
end
def self.find_by_talent(talent)
self.where("profile.talents.name" => talent)
end
end
The services controller :
# POST /services
# POST /services.json
def create
#service = Service.new(service_params)
respond_to do |format|
if #service.save
format.html { redirect_to #service, notice: 'Service was successfully created.' }
format.json { render action: 'show', status: :created, location: #service }
else
format.html { render action: 'new' }
format.json { render json: #service.errors, status: :unprocessable_entity }
end
end
end
...
def service_params
params.require(:service).permit(:date, :time, :place, :name, :theme, :team => [:id, :precedence, :message ], :band => [:id, :lead, :guitar ])
end
And the form in _form.html.erb :
<%= form_for(#service) do |f| %>
...
<%= f.fields_for #service.team do |tf| %>
<%= tf.collection_select :presidence, User.find_by_talent(:presidence), :_id, :fullname, {:include_blank => "select a person"} %>
<%= tf.collection_select :message, User.find_by_talent(:message), :id, :fullname, {:include_blank => "select a person"} %>
<% end %>
<%= f.fields_for #service.band do |bf| %>
<%= bf.collection_select :lead, User.find_by_talent(:lead), :id, :fullname, {:include_blank => "select a person"} %>
<%= bf.collection_select :guitar, User.find_by_talent(:guitar), :id, :fullname, {:include_blank => "select a person"} %>
<% end %>
...
<% end %>
When creating a service, everything seems to run fine, but this is what I get in the console :
2.0.0-p195 :001 > s = Service.last
=> #<Service _id: 52ea18834d61631e7e020000, date: "2014-02-02", time: "10:00", place: "Where it's at", name: "My great name", theme: "The service's theme">
2.0.0-p195 :002 > s.team
=> #<Team _id: 52ea18834d61631e7e030000, >
2.0.0-p195 :003 > s.team.presidence
=> nil
Why is s.team.presidence not created ? s.team looks weird, too, with an ending comma...
Here is the content of my rails log :
Started POST "/services" for 127.0.0.1 at 2014-01-30 10:16:51 +0100
Processing by ServicesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Ph6lbdHC2FbiANn/fGSzHWprenj3fWKXM40Hrsc5+AM=", "service"=>{"date"=>"2014-02-02", "name"=>"My great name", "theme"=>"The service's theme", "time"=>"10:00", "place"=>"Where it's at", "team"=>{"presidence"=>"52ea18324d61631e81010000", "message"=>"52ea18324d61631e81010000"}, "band"=>{"lead"=>"52ea18324d61631e81010000", "guitar"=>"52ea18324d61631e81010000"}}, "commit"=>"Create Service"}
MOPED: 127.0.0.1:27017 COMMAND database=admin command={:ismaster=>1} runtime: 0.6610ms
MOPED: 127.0.0.1:27017 UPDATE database=service_boot_camp_development collection=users selector={"band_id"=>BSON::ObjectId('52ea18834d61631e7e010000'), "_id"=>{"$nin"=>[]}} update={"$set"=>{"band_id"=>nil}} flags=[:multi]
COMMAND database=service_boot_camp_development command={:getlasterror=>1, :w=>1} runtime: 0.5800ms
MOPED: 127.0.0.1:27017 INSERT database=service_boot_camp_development collection=services documents=[{"_id"=>BSON::ObjectId('52ea18834d61631e7e020000'), "date"=>"2014-02-02", "time"=>"10:00", "place"=>"Where it's at", "name"=>"My great name", "theme"=>"The service's theme", "team"=>{"_id"=>BSON::ObjectId('52ea18834d61631e7e030000')}, "band"=>{"_id"=>BSON::ObjectId('52ea18834d61631e7e010000')}}] flags=[]
COMMAND database=service_boot_camp_development command={:getlasterror=>1, :w=>1} runtime: 2.7460ms
I guess I'm doing something wrong, but I have no clue if it is in the database model or in the form... or anything else...
You will not be able to do it this way. When you create an embedded document, its _id and all of its data are embedded directly within the parent document. This is in contrast to an association, where the document with the belongs_to gets a foreign key which points to its associated parent document. So here, your User documents each have a team_id and band_id, but when the database tries to get the documents, it can't find them, since you can't query directly for embedded documents; you need the parent document first. For more, see the Mongoid documentation.
Another potential issue is that you have multiple belongs_to definitions in the User models. This will also cause an issue, because for each one of those, Mongoid will attempt to create a team_id and band_id. You should name them separately and specify a class name; perhaps names like :presiding_team and :message_team, :lead_band and :guitar_band, etc. This answer should show you what that would look like.
I would recommend making the Team and Band separate referenced documents instead of embedded documents, since you won't be able to reference users effectively while they're embedded.
Hope this helps.

Rails 4 testing controller spec ,devise helper sign_in doesn't work

I have Rails 4.2.6 and rspec 3.3.0 , devise version 3.5.8 and i have trouble to test my controller specs always getting error saying ("expected the response to have a success status code (2xx) but it was 401")
Later when i try different spec I am always getting failure message ("Your account is not enabled yet !"), any ideas ?, any help much appreciated ..
my spec:
require 'rails_helper'
describe MyController, :type => :controller
let(:user) { create(:user) }
let(:campaign) { create(:campaign, user: user) }
let!(:placement) { create(:placement, user: user, campaign: campaign, end_date: Date.today) }
before(:each) do
sign_in user
end
context "when we have no data" do
before do
get :graph_data, format: :json
#json = JSON.parse(response.body)
end
it "should be a success" do
expect(response).to have_http_status(:success)
end
end
end
I have following spec_helper:
config.include Devise::TestHelpers, :type => :controller
config.before(:each) do
DatabaseCleaner.start
end
factory defined:
FactoryGirl.define do
factory :unconfirmed_user, class: User do
sequence(:email) { |n| "john#{n}#email.com" }
sequence(:name) { |n| "John Nice #{n}" }
password 'password'
password_confirmation 'password'
factory :user do
confirmed_at Time.now.utc
factory :admin do
organisation { create(:organisation, :some_organisation) }
end
end
end
controller:
MyController < ApplicationController
def graph_data
items = current_user.items //outputs [1,2,3,45,5]
render json: items, status: :ok
end
end
routes:
GET /mycontroller/graph_data(.:format)
i found what was the issue,on User model had a method 'active_for_authentication?'
def active_for_authentication?
super && (group.include?('company-group) || is_admin? )
end
Method 'active_for_authentication?' is a Devise public method
and when it is defined in your model like (User), you change behaviour of it, and in my case it was overwritten with different behaviour,
checking for belonging user to the 'company-group' or not ..
That's why i had failure message ("Your account is not enabled yet !")