I get this error message:
Completed 500 Internal Server Error in 5ms (ActiveRecord: 0.0ms)
NoMethodError (undefined method `avatar=' for #<User::ActiveRecord_Relation:0x007f87e4c304d8>):
app/controllers/api/v1/user_controller.rb:10:in `upload'
Model:
class User < ActiveRecord::Base
acts_as_token_authenticatable
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
mount_uploader :avatar, AvatarUploader
validates_presence_of :avatar
validates_integrity_of :avatar
validates_processing_of :avatar
end
Controller:
module Api
module V1
class UserController < ApplicationController
before_action :set_user, only: [:show, :update, :destroy]
#before_filter :authenticate_user_from_token!
def upload
puts "here => " + params[:user][:email].to_s
#user = User.where(email: params[:user][:email])
#user.avatar = params[:user][:file]
#user.save!
p #user.avatar.url # => '/url/to/file.png'
p #user.avatar.current_path # => 'path/to/file.png'
p #user.avatar_identifier # => 'file.png'
end
...
environment.rb:
# Load the Rails application.
require File.expand_path('../application', __FILE__)
require 'carrierwave/orm/activerecord'
# Initialize the Rails application.
Rails.application.initialize!
The AvatarUploader was generated and the avatar:string column was added to the users table through the migration execution. I am not sure what's wrong with it.
Extra info: I use Rails: 4.2.4, Ruby: 2.2.1
Many thanks !
The error is pretty informative. When you call User.where(email: params[:user][:email]) you don't get a User object, you get an ActiveRecord_Relation object, wich can contain multiple ActiveRecord objects or be empty. To get a single User you want to use find_by instead of where, then you'll be able to get access to the avatar.
Related
I am developing a web-app using Ruby on Rails (4.2.0) and I faced the implementation the login via Oauth (I followed the RailsCast tutorials #235 and #236). In particular for the authentication I implemented the following model
class Authentication < ActiveRecord::Base
# an authentication entry belongs to one user
belongs_to :user
# provider must be present
validates :provider, presence: true
# uid must be present
validates :uid, presence: true
# uniqueness of the couple user_id - provider
validates_uniqueness_of :user_id, :scope => :provider
end
and the associated create action for the authentication controller is
def create
omniauth = request.env["omniauth.auth"]
authentication =Authentication.find_by_provider_and_uid(omniauth['provider'],omniauth['uid'])
if authentication
flash[:success] = "Welcome back #{omniauth['info']['name']}!"
log_in(authentication.user)
redirect_to root_url
elsif current_user
current_user.authentications.create(provider: omniauth['provider'], uid: omniauth['uid'])
flash[:success] = "Welcome #{omniauth['info']['name']}!"
redirect_to root_url
else
user = User.new
user.authentications.build(:provider => omniauth ['provider'], :uid => omniauth['uid'])
if user.save
flash[:success] = "Signed in successfully."
redirect_to root_url
else
session[:omniauth] = omniauth.except('extra')
flash[:info] = "Just one step to go!"
redirect_to signup_url
end
end
end
While route.rb configuration file contains
match '/auth/:provider/callback' => 'authentication#create', via: [:get, :post]
Now I get stucked in writing down the controller test for two main reasons:
How can I make the post in test? With the following test unit
class AuthenticationControllerTest < ActionController::TestCase
test "post request" do
post :create
end
end
I get the following error
ActionController::UrlGenerationError: ActionController::UrlGenerationError: No route matches {:action=>"create", :controller=>"authentication"}
test/controllers/authentication_controller_test.rb:6:in `block in <class:AuthenticationControllerTest>'
test/controllers/authentication_controller_test.rb:6:in `block in <class:AuthenticationControllerTest>'
How can I create a "fake" env variable for the test?
Surfing the web I was able to find only tutorials using Capybara or Cucumber and nothing with the standard Rails tests.
Any kind of help will be really appreciated!
Andrea
I have a problem with devise_invitable 1.4.0 and strong parameters when I add additional custom parameters and I really hope somebody can guide me in the right direction. I am able to send invitations, but when an invited user accepts an invitation and enters a desired username, maiden name, password and confirmed password, the following error is shown:
Processing by Users::InvitationsController#update as HTML
Unpermitted parameters: username, name
The user is created as expected, but the 'username' and 'name' columns in the database are empty.
I have tried all the suggestions I could find for related issues, but none of the worked. I have noticed that if I change the app/controllers/users/invitations_controller.rb file in any way (eg inserting a blank space on an empty line) without restarting the webserver (Thin) the problem disappears - but the problem reappears when the webserver is restarted.
The various relevant files look like this:
routes.rb:
Rails.application.routes.draw do
root to: 'visitors#index'
#Tell rails to use the Devise controllers that were generated with this command:
# > rails generate devise:controllers users
#Using these generated controllers allows us to overwrite anything in the deault controllers.
devise_for :users, :path_names => {:sign_in => 'login', :sign_out => 'logout'}, controllers: {confirmations: "users/confirmations", passwords: "users/passwords", registrations: "users/registrations", sessions: "users/sessions", unlocks: "users/unlocks", :invitations => 'users/invitations'}
resources :users
end
config/initializers/devise.rb
Devise.setup do |config|
...
...
config.scoped_views = true
config.authentication_keys = [ :username ]
...
...
end
app/controllers/users/invitations_controller.rb:
class Users::InvitationsController < Devise::InvitationsController
private
# this is called when creating invitation
# should return an instance of resource class
def invite_resource
## skip sending emails on invite
resource_class.invite!(invite_params, current_inviter) do |u|
u.tenant = current_inviter.tenant
u.role = :user
end
end
def after_invite_path_for(resource)
users_path
end
def resource_params
params.permit(user: [:name, :email,:invitation_token, :username])[:user]
end
end
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
around_filter :scope_current_tenant
before_filter :configure_permitted_parameters, if: :devise_controller?
if Rails.env.development?
# https://github.com/RailsApps/rails-devise-pundit/issues/10
include Pundit
# https://github.com/elabs/pundit#ensuring-policies-are-used
# after_action :verify_authorized, except: :index
# after_action :verify_policy_scoped, only: :index
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
end
#############################################################################
private
#############################################################################
if Rails.env.development?
def user_not_authorized
flash[:alert] = "Access denied." # TODO: make sure this isn't hard coded English.
redirect_to (request.referrer || root_path) # Send them back to them page they came from, or to the root page.
end
end
def current_tenant
#current_tenant ||= current_user.tenant unless current_user.nil?
end
helper_method :current_tenant
def scope_current_tenant(&block)
if current_tenant.nil?
scope_visitor_schema
yield
else
current_tenant.scope_schema("public", &block)
end
end
def scope_visitor_schema()
original_search_path = ActiveRecord::Base.connection.schema_search_path
ActiveRecord::Base.connection.schema_search_path = 'public'
ensure
ActiveRecord::Base.connection.schema_search_path = original_search_path
end
#############################################################################
protected
#############################################################################
def configure_permitted_parameters
# Only add some parameters
devise_parameter_sanitizer.for(:account_update).concat [:name, :email]
# Override accepted parameters
devise_parameter_sanitizer.for(:accept_invitation) do |u|
u.permit(:name, :username, :password, :password_confirmation,
:invitation_token)
end
end
end
app/models/user.rb:
class User < ActiveRecord::Base
enum role: [:user, :admin]
after_initialize :create_tenant, :if => :new_record?
belongs_to :tenant
# has_many :invitations, :class_name => self.to_s, :as => :invited_by
scope :unconfirmed, -> { where(confirmed_at: nil) }
scope :confirmed, -> { where.not(confirmed_at: nil) }
# validate :username, presence: true, uniqueness: true, format: { with: /[a-zA-Z0-9]{4,20}/ }
def displayed_username
username.nil? ? "N/A" : username
end
def displayed_name
name.nil? ? "N/A" : name.titleize
end
def create_tenant
#The create_tenant method will also be called when looking up a user,
#so the following ensures a tenant is only created if it does not already
#exist - and the user has not been invited and assigned to an existing tenant:
if self.tenant.nil?
#Set role to 'admin' if a tenant is about to be created:
self.role = :admin #if self.tenant.nil?
self.tenant = Tenant.new
end
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :invitable, :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
end
I finally found a fix, which was to place the parameter sanitizer directly in users/invitations_controller.rb instead of the application_controller.rb.
class Users::InvitationsController < Devise::InvitationsController
before_filter :configure_permitted_parameters, if: :devise_controller?
private
def configure_permitted_parameters
devise_parameter_sanitizer.for(:accept_invitation) do |u|
u.permit(:username, :name, :email, :password, :password_confirmation, :invitation_token)
end
end
end
I am very new in rails I have built a form from my model #user
this is my user controller
def me
#user = User.find_by_id(current_user.id)
if !params.empty?
#user.update_attributes params[:user]
end
end
But I getting this error:
ActiveModel::ForbiddenAttributesError
this is my model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
private
def user_params
params.require(:user).permit(:name, :surname, :email, :phone, :mobile)
end
end
I tried to define here an "update" method, but I get errors like this:
ActiveModel::ForbiddenAttributesError
Any idea?
Ok so a few things here
Your update method should look like this
def me
#user = current_user.find_by(params[:Id])
end
You need to have your permitted Params in your controller, and add :Id to those Params
As it looks like your using devise you will need to make your own user controller inheriting from devises controller so that you can override the permitted Params
See the devise docs on how to override the controller as its really simple
I'm attempting to write out some unit tests for my Rails application using RSpec. I'm using Rails 4.0.0 and Rspec-Rails 2.14.6. My User model:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable, :omniauth_providers => Settings.authentication.providers.map { |i| i.to_sym }
validates :password, presence: true, allow_nil: true,
allow_blank: true, if: :password_required?
validates :email, presence: true
def password_required?
self.providers.empty?
end
has_many :providers
has_one :profile
end
And my (magical) spec:
require 'spec_helper'
describe User do
describe '.new' do
it 'can create a valid user with no providers' do
params = ActionController::Parameters.new(FactoryGirl.attributes_for :user)
u = User.create params.permit!
expect(u).to be_new_record
end
end
describe '.build_with_provider' do
it 'can create a valid user with a provider' do
puts ap(User)
provider = FactoryGirl.create :provider
oauth_data = FactoryGirl.attributes_for :oauth_data
u = User.build_from_provider_and_oauth_data provider, oauth_data
expect(u).to_not be_nil
expect(u).to be_new_record
expect(u).to be_valid
u.save
expect(u).to be_persisted
end
end
end
If I'm missing something, please let me know. As far as I know, using ActionController::Parameters is the new way of (white|black)listing parameters in Rails 4.
I cannot get postmark to handle registration and forgot password emails:
user_mailer.rb
class UserMailer < ActionMailer::Base
include Devise::Mailers::Helpers
default from: "donotreply#barnpix.com"
def confirmation_instructions(record)
devise_mail(record, :confirmation_instructions)
end
def reset_password_instructions(record)
devise_mail(record, :reset_password_instructions)
end
def unlock_instructions(record)
devise_mail(record, :unlock_instructions)
end
# you can then put any of your own methods here
end
application.rb
config.action_mailer.delivery_method = :postmark
config.action_mailer.postmark_settings = { :api_key => ENV['9302106a-63xxxx-xxx-xx-'] }
user.rb
devise :database_authenticatable, :registerable, :recoverable,
:rememberable, :trackable, :validatable
devise.rb
config.mailer = "UserMailer" # UserMailer is my mailer class
I cannot get this to work at all. Any hints as to what I might be doing wrong or what I might be missing to get this to work ?
I think your problem is caused by this line:
config.action_mailer.postmark_settings = { :api_key => ENV['9302106a-63xxxx-xxx-xx-'] }
ENV is a hash of all environment variables. You should use names to access the values. I guess you’re using Postmark on Heroku, so it will be ENV['POSTMARK_API_KEY'] in that case.