Rails - Show Action & View for models with one-to-one association? - ruby-on-rails-3

I have a simple app with a User model & an Instructor_Profile model. The associations between these two models is one-to-one. I cannot get my view show.html.erb to render. I am simply trying to display a single attribute from the Instructor_Profile model and I get this error:
NoMethodError in Instructor_profiles#show
undefined method `name' for nil:NilClass
Any help would be greatly appreciated!
Models:
class User
has_one :instructor_profile
class InstructorProfile
belongs_to :user
UsersController:
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
UserMailer.welcome_email(#user).deliver
render 'static_pages/congratulations'
else
render 'new'
end
end
InstructorProfilesController:
def new
#instructor_profile = current_user.build_instructor_profile
end
def create
#instructor_profile = current_user.build_instructor_profile(params[:instructor_profile])
if #instructor_profile.save
flash[:success] = "Profile created!"
redirect_to root_path
else
....
end
end
def show
#user = User.find(params[:id])
#instructor_profile = #user.instructor_profile
end
Views/instructor_profiles/show.html.erb:
<p>Display Name: <%= #user.instructor_profile.name %></p>

It happens because #user.instructor_profile is nil.
That means there is no instructor_profile corresponding to the #user.
Please check the create method inside the UserController to confirm whether instructor_profile is creating or not. Code should be something like this,
#user.instructor_profile = InstructorProfile.new(name: "my_name")
#user.instructor_profile.save
edited:
has_one association doesn't mean that every user has to have an instructor_profile. So before you call the #user.instructor_profile.name, just confirm that #user have instructor_profile or not. In your view, you can easily solve this error by adding one condition..
<p>Display Name: <%= #user.instructor_profile ? #user.instructor_profile.name : "no instructor_profile present" %></p>.
One more thing, in instructor_profiles_controller/show, change the code into
#instructor_profile = InstructorProfile.find(params[:id])
#user = #instructor_profile.user

Related

NoMethodError in Controller#show - Nested model

It might look like a newbie question but I can't get my head around it. Rails is telling me that the method is not defined even if I can access it in the console. I'm missing something obviously...
Here is my routes.rb file:
Rails.application.routes.draw do
root 'static_pages#home'
resources :users do
resources :bodies
end
end
Here is the User model
class User < ApplicationRecord
has_many :bodies, dependent: :destroy
end
Here is the Body model
class Body < ApplicationRecord
belongs_to :user
end
Here is the Bodies Controller
class BodiesController < ApplicationController
def new
#user = User.find(params[:user_id])
#body = #user.bodies.new
end
def create
#body = current_user.bodies.build(body_params)
if #body.save
redirect_to user_body_path(#body)
else
render 'new'
end
end
def show
#user = User.find(params[:user_id])
#body = #user.bodies(params[:id])
end
def index
#bodies = Body.all
end
private
def body_params
params.require(:body).permit(:weight, :sex, :age, :fat)
end
end
The create action is working fine. I'm just struggling to get the Show action to work although the right parameters are passed along :
Showing /Users/rodolphegeant/code/FFL/app/views/bodies/show.html.erb where line #9 raised:
undefined method `sex' for #<Body::ActiveRecord_Associations_CollectionProxy:0x007f820f65da90>
Did you mean? send
Extracted source (around line #9):
7
8
9
10
11
12
Hello from my Body
<%= #body.sex %> | <%= #body.age %> | <%= #body.weight %> | <%= #body.fat %>
Rails.root: /Users/rodolphegeant/code/FFL
Application Trace | Framework Trace | Full Trace
app/views/bodies/show.html.erb:9:in `_app_views_bodies_show_html_erb___2597620731841156962_70098290142700'
Request
Parameters:
{"user_id"=>"1", "id"=>"3"}
When I go to the console I can run #body.sex or #body.age or any other method that corresponds to the attributes I'm looking for....
Thanks a lot in advance for helping me resolve this issue.
Codingly yours,
Rodolphe
You should run find query on records which will return from the association with user model.
def show
#user = User.find(params[:user_id])
#body = #user.bodies.find(params[:id])
end
HI in show action in your controller replace #user.bodies(params[:id]) by Body.find(params[:id])

Clearance failure when forbidden password reset

I’m using clearance and love it, but I'm having trouble resetting passwords. I type in my email to reset the password, which works, but then when I try to navigate to the edit password page using the reset token, I get the failure when forbidden flash error “Please double check the URL or try submitting the form again” and it redirects me back. I get the same error in my tests.
I think this has something to do with my before_action statements, but I just don’t know how to fix them. I have researched questions like this to no avail.
I'm sure it's a stupid question, but I'm new so I really appreciate any help. Please let me know if this isn't enough code.
class UsersController < Clearance::UsersController
before_action :require_login, only: [:create] # does this need to be in both user controllers?
...
def user_params
params.require(:user)
end
end
And here is the clearance controller.
class Clearance::UsersController < ApplicationController
before_action :require_login, only: [:create]
require 'will_paginate/array'
def new
#user = user_from_params
render template: 'users/new'
end
def create
#user = user_from_params
#user.regenerate_password
if #user.save
sign_in #user unless current_user
UserMailer.welcome_email(#user).deliver!
redirect_to users_path
else
render template: 'users/new'
end
end
def edit
#user = User.friendly.find(params[:id])
end
def update
#user = User.friendly.find(params[:id])
if #user.update(permit_params)
redirect_to #user
flash[:success] = "This profile has been updated."
else
render 'edit'
end
end
private
def avoid_sign_in
redirect_to Clearance.configuration.redirect_url
end
def url_after_create(user)
dashboards_path(user)
end
def user_from_params
user_params = params[:user] || Hash.new
is_public = check_public_params(user_params)
first_name = user_params.delete(:first_name)
last_name = user_params.delete(:last_name)
email = user_params.delete(:email)
password = user_params.delete(:password)
parish = user_params.delete(:parish)
division = user_params.delete(:division)
admin = user_params.delete(:admin)
Clearance.configuration.user_model.new(user_params).tap do |user|
user.first_name = first_name
user.last_name = last_name
user.password = password
user.email = email
user.is_public = is_public
user.parish_id = parish.to_i
user.division = division
user.admin = admin
end
end
def permit_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :is_public, :parish_id, :division, :admin)
end
end
EDIT: relevant portions of routes.rb
Rails.application.routes.draw do
resources :passwords, controller: "clearance/passwords", only: [:create, :new]
resource :session, controller: "clearance/sessions", only: [:create]
resources :users, controller: "clearance/users", only: [:create] do
resource :password,
controller: "clearance/passwords",
only: [:create, :edit, :update]
end
get "/sign_in" => "clearance/sessions#new", as: "sign_in"
delete "/sign_out" => "clearance/sessions#destroy", as: "sign_out"
get "/sign_up" => "clearance/users#new", as: "sign_up"
constraints Clearance::Constraints::SignedOut.new do
root to: 'high_voltage/pages#show', id: 'landing'
end
constraints Clearance::Constraints::SignedIn.new do
# root to: 'dashboards#index', as: :signed_in_root
root to: 'high_voltage/pages#show', id: 'parish_dashboard', as: :signed_in_root
end
# constraints Clearance::Constraints::SignedIn.new { |user| user.admin? } do
# root to: 'teams#index', as: :admin_root
# end
resources :users do
collection { post :import }
end
It turns out there was a conflict between the way I was finding the user instance in the password reset link. Clearance finds users simply by using #user, but since I'm using FriendlyId I needed to change that to #user.id.
So instead of...
<%= link_to 'Change My Password', edit_user_password_url(#user, token: #user.confirmation_token.html_safe) %>
I did
<%= link_to 'Change My Password', edit_user_password_url(#user.id, token: #user.confirmation_token.html_safe) %>
Thanks, Thoughbot, for this great gem!

uninitialized constant ProfilesController

I have an error "uninitialized constant ProfilesController" on my Profiles controller. This is the profiles_controller.rb:
class ProfilesController < ApplicationController
def new
#profile = Profile.new
end
def create
#profile = Profile.new(params[:profile])
if #profile.save
redirect_to profile_path, notice: I18n.t('.profile.created')
else
render action: "new"
end
end
end
This is the routes.rb:
resources :profiles, only: [:new, :create]
And this the output of rake routes:
profiles POST /profiles(.:format) profiles#create
new_profile GET /profiles/new(.:format) profiles#new
When I click a link for "new_profile_path" I get the error, but to me everything seems OK? The controller name is plural,the routes are OK?
You most likely spelled your controller file wrong. Confirm that file is truly: `/app/controllers/profiles_controller.rb'
Really strange, I created a Books controller with a generator, renamed everything to Profiles and then it works as normal. As far as I can see the routes are identical. Strange....
I had the same problem when i checked the name of the controller was 'profile_controller.rb'(i had created it manually though). but inside the definition it was "ProfilesController".
class ProfilesController < ApplicationController
def index
end
def new
#profile = Profile.new
end
def create
end
end
So if your controller name is correct and you have added the route("resources :profiles") then it will work as expected

rails controller model view advice for ContacUs page

I have a simple static website written in rails 3.
The site has one controller called pages and each static page is served as view. Such as pages/home, pages/about, pages/prices, etc. This all works great.
I've now run into a problem where I need to add a simple contactus feature but I'm struggling to get my head round the model/controller/views for this.
I already have a pages controller with a contactus view, that view has details addresses etc. Now I somehow need to get a message model into the contactus view so I can populate the model attirbutes and send the email.
Can I / Should I just create a new message model from within the Pages Controller as in ,
class PagesController < ApplicationController
def contact
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.valid?
# TO DO send message here using OS mail program.
redirect_to root_url, notice: "Message sent! Thank you for contacting us."
else
render "new"
end
end
end
def about
end
def products
end
def portfolio
end
def services
end
end
Or should I take out the contactus view from the pages controller and make new controller called messages ?
Thanks.
I would have a separate controller called contact for example with new and create actions
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.valid?
NotificationsMailer.new_message(#message).deliver
redirect_to(root_path, :notice => "Message was successfully sent.")
else
flash.now.alert = "Please fill all fields."
render :new
end
end
end
Then a separate model to handle your messages
class Message
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :subject, :body, :file
validates :name, :email, :subject, :body, :presence => true
validates :email, :format => { :with => %r{.+#.+\..+} }, :allow_blank => true
end
your attributes can be anything you like, obviously this is just an example of what you can do

How can I add a custom column in authlogic?

I've created a simple user system with authlogic using Rails 3. I want to add an "account_type" column to the database. How can I populate this column in the database when the user signs up? I have very very little experience with Rails.
Update: So I know somewhere in "#user = User.new(params[:user])" I need to add :account_type = "user". What's the right syntax for this though?
Here's what I have in my user controller:
class UserController < ApplicationController
before_filter :require_no_user, :only => [:new, :create]
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "Registration successful!"
redirect_to root_url
else
render :action => :new
end
end
end
Thanks in advance!