Pass Account id (parent) to User (child) with Devise in Rails - ruby-on-rails

I have set up the necessary models and views to have a Devise resource, Account and User. Account has_many users & User belongs_to account. The schema reflects account_id as an attribute of user. I'm probably mistaken but I was under the impression that this account_id attribute would automatically be filled when an Account is logged in & creates a new user. Upon checking the Rails console, it seems all new users created this way had a nil value for account_id. Separate question but is this the ideal way to have multitenancy in an application using Devise?
Models:
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :account, :inverse_of => :users
accepts_nested_attributes_for :account
end
account.rb
class Account < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :users, :inverse_of => :account, :dependent => :destroy
accepts_nested_attributes_for :users
has_many :projects
end
schema.rb (just users & accounts)
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "account_id"
t.boolean "supervisor"
t.string "name"
end
create_table "accounts", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
end
users_controller.rb
class UsersController < ApplicationController
before_filter :authenticate_user!
def new
#user = User.new
end
def create
#user.skip_confirmation! # confirm immediately--don't require email confirmation
if #user.save
flash[:success] = "User added and activated."
redirect_to users_path # list of all users
else
render 'new'
end
end
def index
#users = User.all
end
end
accounts_controller.rb
class AccountsController < ApplicationController
def new
#accounts = Account.new
#accounts.users.build
end
def create
#account = Account.new(params[:account])
if #account.save
flash[:success] = "Account created"
redirect_to accounts_path
else
render 'new'
end
end
end
from registrations > edit.html.erb
<% if account_signed_in? %>
<div class="jumbotron">
<span><%= link_to "Add user", new_user_registration_path, class: "btn btn-primary btn-sm" %></span>
</div>
<% end %>

I am not sure what how exactly you are trying to create a user
But creating a user with
#account.users.build
would automatically add account_id to user object.
Hope this helps! :)

Related

Unsure if association is working in my rails app

My app has users and users are able to post links to my app. I have an association set up so that a user has many :links and links belong_to a user (see below for models). Now I am trying to get the users email to appear in the show template and I am getting a nil value for Link.user for new links. Can someone maybe shed some light as to why? Is my association incorrect? The user has been logged in when posting links.
User model:
class User < ActiveRecord::Base
has_many :links
acts_as_voter
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Link model:
class Link < ActiveRecord::Base
belongs_to :user
acts_as_votable
attr_accessor :avatar
mount_uploader :avatar, AvatarUploader
end
show.html.erb:
<%= time_ago_in_words(#link.created_at) %> by <%= #link.user.try(:email) %>
Schema:
create_table "links", force: :cascade do |t|
t.string "title"
t.string "url"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Link creation in Links controller;
def new
#link = Link.new
end
def create
#link = Link.new(link_params)
if #link.save
redirect_to root_path
else
render 'new'
end
end
private
def link_params
params.require(:link).permit(:title, :url, :avatar)
end
Make sure the links are actually being assigned to a user when created.
Using the rails console. Try looping through the links and making sure they have user_ids:
in the rails console:
ap Link.all.map(&:user)
If they are indeed owned by a user
<%= #link.user.email %>
should print out the email.
You should be able to do something like this in your controller:
#user.links << params[:new_link]
Make sure that much is working.
You are using devise. Inside your Link controller, you have to authenticate your logged on user.
# app/controllers/links_controller.rb
before_action :authenticate_user!
def create
#link = current_user.links.new(link_params)
if #link.save
redirect_to root_path
else
render 'new' # generally this is a render 'edit'
end
end
I truncated the file here. Please read the devise manual

undefined method `firstname' for nil:NilClass Rails4

Can somebody help me with this error? I add profile controller by console without model. Database it's working fine. I am sure that i have lastname and firstname in seed.rb and i just did db:setup/migration.
Here's the show.html
.page-header
.h1
=link_to #user.firstname + " " + #user.lastname, edit_user_registration_path
Database:
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "firstname"
t.string "lastname"
t.string "username"
t.boolean "admin", default: false
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :reviews
has_many :products
validates_presence_of :firstname, :lastname
end
Profile controler:
class ProfileController < ApplicationController
def show
#user = User.find_by_username(params[:id])
if #user
#reviews=#user.reviews.order(:created_at).reverse_order.limit(5)
render action: :show
end
end
end
This part
#user = User.find_by_username(params[:id])
returns nil, because you pass id from params as a username to find_by_username finder. In can't find the username (string) which is id (integer).
It should be
#user = User.find(params[:id])
Take a look at docs on how finders work
If you are using find_by_username then you should pass params[:username] instead of params[:id] .
Also this part:
if #user
#reviews=#user.reviews.order(:created_at).reverse_order.limit(5)
render action: :show
end
even if the if statement is false, render action: :show will still be called - it's the default.
if you defined a method that said nothing:
def test
end
rails would call: render action: :name_of_method
You need to use a redirect and unless:
redirect_to users_url, notice: 'user not found' unless #user
Good luck!

As I can create with username profile page Rails

I am unable to find accurate information to what I want, so my second choice is to ask.
So, I want to know how to create a user profile from scratch and with your username replacing the ID.
Example: http://example.com/profile/{username}
In this case I have no problems with usernames, as are those working on a game server and they can not contain spaces or unusual characters.
I have done something, but I think it is wrong, even though I do not have any error on my website.
Notes:
My Devise Model: Player/s
Schema of Players
create_table "players", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "admin", default: false
t.integer "role_id"
t.string "nick"
t.string "username"
end
Variables "admin and role_id" are for charges will have on the web. I think this is not relevant to the subject.
Looked at other tutorials, but I have no more special things to add to my code.
My Controllers:
- registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
new_path(resource)
end
end
profile_controller.rb
class ProfileController < ApplicationController
def members
end
def myProfile
#attributes = Profile.attribute_names - %w(id player_id created_at updated_at)
end
def new
#profile = current_player.build_profile
end
def create
#profile = current_player.build_profile(params[:profile].permit( :nick))
end
end
My Models:
- player.rb
class Player < ActiveRecord::Base
validates :email, :presence => true, :email => true
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :role
before_create :set_default_role
has_one :profile
private
def set_default_role
self.role ||= Role.find_by_name('registered')
end
end
profile.rb
class Profile < ActiveRecord::Base
belongs_to :players
end
And in my view, have the controller profiles with:
myProfile => Only the profile of the user
profiles that is the global view of the profiles
route.rb
get 'profile/:id' => 'profile#perfiles'
resources :profile, only: [:edit]
map.resources :players, :has_one => :profile
map.resources :profiles
I hope I'm not asking for much, but hey, it's a question that I have and worth a try.
Thanks in advance, if anything is missing tell me.
I believe what you're looking to do is override the named route parameter. See this rails guide for more details: http://edgeguides.rubyonrails.org/routing.html (section 4.10).
Basically, you'll want to just add the param: :username to your routes file:
resources :profile, only: [:edit], param: :username
Which will make your route look something like:
profile GET /profile/:username(.:format) profile#show
And in your controller:
#profile = Profile.find_by(username: params[:username])
Hope that helps!

Devise - how to test admin credentials with Rspec

I am using Devise to login users to the application.
I am trying to pass following test. Firstname and lastname pass but "expect(User.new).to_not be_admin" doesn't passs.
Each time I get message as below.
"Failure/Error: expect(User.new).to_not be_admin expected # to respond to 'admin?'"
Any suggestions how to pass such test? I think the problem is in to_not be_admin - but I'm really new to testing software. I've googled for this but with no result. Many thanks in advance for help.
spec/models/user_spec.rb
require 'spec_helper'
describe User do
it { should validate_presence_of (:firstname) }
it { should validate_presence_of (:lastname) }
it "by default isn't admin" do
expect(User.new).to_not be_admin
end
end
User Model (User.rb):
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :reviews
has_many :products
validates_presence_of :firstname
validates_presence_of :lastname
end
My users table looks like this:
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "firstname"
t.string "lastname"
t.boolean "admin", default: false
end

Issue with belongs_to and user (devise)

I'm new to RoR, and I would like to develop an app, but I have an issue with the belongs_to association. I am using devise for the authentication of my users, and I have an object called timesheet, I followed several tutorials and read a lot of forums but unfortunately user_id remains null in my db, so I do not know where does the problem come from.
If you can tell how to fix it, any links that can helps me, that would be great.
Schema.rb:
ActiveRecord::Schema.define(version: 20150128160116) do
create_table "timesheets", force: true do |t|
t.date "date"
t.time "working_start_time"
t.time "working_end_time"
t.integer "breaks"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "timesheets", ["user_id"], name: "index_timesheets_on_user_id"
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.integer "current_sign_in_ip"
t.integer "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
timesheets_controller.rb
class TimesheetsController < ApplicationController
layout 'application'
def show
#timesheet=Timesheet.find(params[:id])
end
def index
#timesheet = Timesheet.all
end
def new
#timesheet = Timesheet.new
end
def create
#timesheet = Timesheet.create(timesheet_params)
redirect_to new_timesheet_path
end
def edit
#timesheet=Timesheet.find(params[:id])
end
def update
#timesheet = Timesheet.find(params[:id])
#timesheet.update_attributes(timesheet_params)
redirect_to student_table_path
end
user.rb 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
has_many :timesheets
end
Timesheet.rb model
class Timesheet < ActiveRecord::Base
belongs_to :user
validates :user_id, :presence => true
end
Thanks in advance.
It will stay null because you are not using it in the timesheetsController, your create action should be like this :
def create
#timesheet = current_user.timesheets.build(timesheet_params)
redirect_to new_timesheet_path
end
You have to use that build method to reference the current_user, so the timesheet will have the current_user in the user_id field.

Resources