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!
Related
I'm new to development, and have spent the last 12 hours (literally) trying to figure out this error message - I'm giving up for the night, but not before a quick cry for help to stackoverflow.
I have this form:
<h2>Select from the language options below (or, <%= button_to "Login", 'users/login', method: :get %></h2>
<%= form_for #language_role do |f| %>
<div id="input">
<h3>I want to learn:</h3><%= select_tag(:language_id, options_from_collection_for_select(Language.all, :id, :lang_name)) %>
</div>
<div>
<p><%= f.submit "Start learning" %></p>
</div>
<% end %>
which is giving me this error message, highlighting the line #language_role = current_user.language_roles.build : "undefined method `language_roles' for nil:NilClass"
I have three tables:
create_table "language_roles", force: :cascade do |t|
t.integer "language_id"
t.boolean "is_active"
t.boolean "is_teacher"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.index ["user_id"], name: "index_language_roles_on_user_id"
end
create_table "languages", force: :cascade do |t|
t.string "lang_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
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
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
The language_roles table is meant to allow a user to have many languages, as well as many roles within that language. Here are my class definitions:
class LanguageRole < ApplicationRecord
belongs_to :languages
belongs_to :users
end
class Language < ApplicationRecord
has_many :language_roles
has_many :users, :through => :language_roles
end
class User < ApplicationRecord
has_many :language_roles
has_many :languages, :through => :language_roles
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
My root path goes to 'home#index', where the user is supposed to pick a language if current_user.language_roles is empty. As such, I put this code in my home controller and language_roles controller:
class HomeController < ApplicationController
def index
#language_role = current_user.language_roles.build
end
end
class LanguageRolesController < ApplicationController
def create
#language_role = current_user.language_roles.build(language_role_params)
if #language_role.save
redirect_to root_path
else
redirect_to :back
end
end
private
def language_role_params
params.permit(:language_id)
end
end
What in the hell is the problem?? I assume I need to instantiate the variable somehow, but I'm not sure how.
Thanks,
Michael
There is a typo in your LanguageRole Model:
LanguageRole < ApplicationRecord
belongs_to :languages
belongs_to :users
end
should be
LanguageRole < ApplicationRecord
belongs_to :language
belongs_to :user
end
belongs_to associations must use the singular term.
The name of the other model is pluralized when declaring a has_many association.
Ref: http://guides.rubyonrails.org/association_basics.html
Your current_user is not defines it seems. You can install a gem called 'pry-rails' and debug your way out of this situation and any other in future. Here's a tutorial how to use it Railscasts #280
In your LanguageRole model you defined like belongs_to :users. But it should be belongs_to :user.
Your model look like ...
LanguageRole < ApplicationRecord
belongs_to :languages
belongs_to :users
end
Which should be something like
LanguageRole < ApplicationRecord
belongs_to :language
belongs_to :user
end
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!
I am trying to create a view for photo uploads for users. I'm new to rails so I'm not quite sure if I am doing this correctly because I'm not quite sure how all the pieces fit. I am using devise and also carrierwave for user authentication and image storage in database. I'm not quite sure what to do with the params for IncomePicture_params. I want to create a view that will allow me to call and display the images and the texts for pictures of the user
I am using rails 4
Models:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:rememberable, :validatable
validates_presence_of :username
has_many :expense_pictures
has_many :income_pictures
end
class IncomePicture < ActiveRecord::Base
belongs_to :user
mount_uploader :image, ImageUploader
has_one :income_text
accepts_nested_attributes_for :income_text
end
class IncomeText < ActiveRecord::Base
belongs_to :income_picture
end
controller:
class UserController < ApplicationController
def create
User.create(user_params)
end
private
def user_params
# required input for params
# permit - returns a version of the params hash with ony the permitted attributes
params.require(:user).permit(:name, :email, :password, :password_confirmation, )
end
end
class IncomePicturesController < ApplicationController
def new
#income_picture = IncomePicture.new(IncomePicture_params)
end
def create
end
def destroy
end
private
def IncomePicture_params
params.require(:income_picture).permit(:image, income_text_attributes: [:amount])
end
end
schema
ActiveRecord::Schema.define(version: 20140723044409) do
create_table "income_pictures", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.string "image"
t.integer "user_id"
end
add_index "income_pictures", ["user_id"], name: "index_income_pictures_on_user_id"
create_table "income_texts", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.integer "income_picture_id"
t.string "amount"
end
add_index "income_texts", ["income_picture_id"], name: "index_income_texts_on_income_picture_id"
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.datetime "remember_created_at"
t.datetime "created_at"
t.datetime "updated_at"
t.string "username"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
end
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! :)
def destroy
#dignity.destroy
end
Sorry, that's not code, that's just how I feel right now. I know there are a ton of beginner questions on Devise, I think I looked at almost every single one.
I have a very simple Devise setup in Rails 3. I did:
rails generate devise User
I'm also running the rails 3 GeoKit plugin,(not sure if that's relevant, just know that I have this other model) so I have another model called Location, and it acts_as_mappable.
Before I post the code, the basic problem is that I cannot seem to get user_id to auto-increment. It was my understanding that a bit of Rails magic should take care of this for me, if I add a column called user_id to Location class. (which I did through a migration.) and then simply set has_many and belongs_to accordingly. (see below)
I can't figure out why user_id is always nil. Does it have something to do with the way the Devise engine works? I am pretty sure I've made this type of association work in the past in the same way when I wasn't using Devise.
user.rb:
class User < ActiveRecord::Base
has_many :locations
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable, :lockable and :timeoutable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
end
location.rb:
class Location < ActiveRecord::Base
belongs_to :user
attr_accessible :street_adress, :city, :state, :zip, :item, :user_id
acts_as_mappable :auto_geocode => true
def address
return "#{self.street_adress}, #{self.city}, #{self.state}, #{self.zip}, #{self.item}"
end
end
here is the migration that added the column:
class AddUseridToLocation < ActiveRecord::Migration
def self.up
add_column :locations, :user_id, :integer
end
def self.down
remove_column :locations, :user_id
end
end
And finally, here is the schema.rb:
ActiveRecord::Schema.define(:version => 20110213035432) do
create_table "locations", :force => true do |t|
t.string "street_adress"
t.string "city"
t.string "state"
t.string "zip"
t.float "lat"
t.float "lng"
t.datetime "created_at"
t.datetime "updated_at"
t.string "item"
t.integer "user_id"
end
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false
t.string "password_salt", :default => "", :null => false
t.string "reset_password_token"
t.string "remember_token"
t.datetime "remember_created_at"
t.integer "sign_in_count", :default => 0
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"
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
EDIT: I'm okay with a RTFM response, as long as I can get a little push in the right direction. I have a suspicion that I need to tell rails something in the create action of my locations_controller.rb ? Someone just give me a little hint here!
def destroy
#dignity.destroy
end
Clearly the first thing to be done is:
raise self.esteem
You say you can't get user_id to "autoincrement". I think what you meant is that user_id is not being assigned (i.e. it is always nil). Can you show the part of the code that assigns a location to a user? Either of these should work:
#user.locations.build
#user.locations << Location.new
EDIT
To expand on this a bit, say you have a request that looks like this:
POST /users/37/locations
And the submitted form contains input name=user[location][name] value="Paris". A typical Rails controller create action might look like this:
def create
#user = User.find(params[:user_id])
#user.locations.build(params[:user][:location])
if #user.save
flash[:notice] = "Location created successfully"
redirect_to user_locations_path(#user)
else
render :new
end
end
The 'magic' is basically Rails inferring from the has_many statement that it needs to set the value of the foreign key column ('user_id') in the related row in the locations table. When you call #user.save it adds a new row in locations and sets user_id to the value of #user.id.