I'm new to Rails and Web Dev and really stumped. I have two models user andproperty. You cannot create a property unless you are a user (logged in). I'm having problems with associations as I have in the user model has_many properties and belongs_to user in property model. When a property is created, when I check the console, it has the correct user_id.
Problem: When I check the user in the console, I get message property_id: nil. Can someone explain what code I need in order for the property_id to populate for the user? (I figure it probably has something to do with the user being created before the property but I thought the associations would automatically take care of this)
I'm using devise in case that is a factor and I added :property_id to the permitted parameters method.
Relevant code is below:
Models:
class Property < ActiveRecord::Base
belongs_to :user, dependent: :destroy
validates :user_id, presence: true
mount_uploader :picture, PictureUploader
end
2)
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 :properties
end
Controllers:
class PropertiesController < ApplicationController
before_action :authenticate_user!, except: [:index]
before_action :set_user, only: [:show, :edit, :update]
def index
#properties = Property.all
end
def new
#property = current_user.properties.new
end
def create
#property = current_user.properties.new(property_params)
respond_to do |format|
if #property.save
format.html { redirect_to #property, notice: "Property was successfully created." }
format.json { render :show, location: #property }
else
format.html { render :new }
format.json
end
end
end
def update
respond_to do |format|
if #property.update(property_params)
format.html { redirect_to #property, notice: "You've successfully updated your property listing!" }
format.json { render :show, status: :ok, location: #property }
else
format.html { render :edit }
format.json { render json: #property.errors, status: :unprocessable_entity }
end
end
end
end
2)
class UsersController < ApplicationController
before_action :authenticate_user!
load_and_authorize_resource
def index
#users = User.all
end
end
Application Controller:
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
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :email, :password, :password_confirmation, :property_id) }
end
What you are doing is wrong, the property_id will not store in User table.
You have one to many relationship. What happens when a single user has 3 properties then you will store 3 property_id in that single user record.
No, beside that you are doing right in your code, Property table will have user_id and you will get all properties of a particular User by doing this in your controller.
#user = User.find(:user_id)
#properties = #user.properties
Related
Firstly apologies as just when i think i have a grip on routing i find that i don't!!
When a registered user logs in to my app they are taken to the admin index view and all i am trying to do is display their user name within that view.
This is my routes config: -
Easygifts::Application.routes.draw do
get 'admin' => 'admin#index'
controller :sessions do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end
get "sessions/create"
get "sessions/destroy"
resources :users
resources :admin
resources :stores do
collection do
get "writing"
get "office"
get "time"
get "home"
get "wellness"
get "travel"
get "bags"
get "leisure"
get "contact"
get "terms"
end
member do
get 'quote'
end
end
resources :products
Users login via the sessions controller and are passed on to the Admin controllers index view. Where i am trying to display their name using the following: - <th colspan="2">Welcome <%= #users.name %></th>
The Sessions controller: -
class SessionsController < ApplicationController
skip_before_action :authorize
def new
end
def create
user = User.find_by(name: params[:name])
if user and user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to admin_url
else
redirect_to login_url, alert: "Invalid user/password combination"
end
end
def destroy
session[:user_id] = nil
redirect_to stores_url, notice: "Logged out"
end
end
The Users Controller: -
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
#users = User.order(:name)
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to users_url, notice: "User #{#user.name} was successfully created." }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to users_url, notice: "User #{#user.name} was successfully updated." }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
begin
#user.destroy
flash[:notice] = "User #{#user.name} deleted"
rescue StandardError => e
flash[:notice] = e.message
end
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :password, :password_confirmation, :add1, :add2, :add3, :add4, :post_code, :home_tel, :mobile, :ice_tel, :ni_number, :position, :image_url, :staff_num, :start_date, :birthday)
end
end
And the Admin Controller: -
class AdminController < ApplicationController
def index
#users = User.find(params[:id])
end
end
My first point of confusion is whether i should be going through the Sessions controller or the Users controller?
If it's in the Sessions controller am i supposed to write something like get 'admin#index' => :show
Or if it's in Users am i to write something like resources :users do member do get 'admin' end end
I think i have to define a controller with an action within my routes but i don't understand in this instance how to work out who is doing what.
Environment:
Windows 8.1
Rails4
Ruby 2
I am using Devise and I have two separate controllers: users_controller.rb and registrations_controller.rb.
Following is my registrations_controller.rb:
class RegistrationsController < Devise::RegistrationsController
before_filter :update_sanitized_params, if: :devise_controller?
def update_sanitized_params
devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:first, :last,
:email, :password,
:password_conf, :password_changed_at)}
devise_parameter_sanitizer.for(:account_update) {|u| u.permit(:first, :last, :salutation,
:email, :password,
:password_conf, :password_changed_at, :current_passwor)}
end
# GET /registrations/new
def new
super
end
# POST /registrations
# POST /registrations.json
def create
#user = User.new(registration_params)
#user.email = #user.email.downcase
##user.slug = "#{#user.first.downcase}_#{#user.last.downcase}_#{#user.email}"
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: t('registration_successfully_created') }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /registrations/1
# DELETE /registrations/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to registrations_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_registration
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def registration_params
params[:user]
end
end
and following is my User model: user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:password_expirable, :confirmable, :lockable, :timeoutable
validates :first, presence: true
validates :last, presence: true
validates :email, :email => true, presence: true, uniqueness: {case_sensitive: false}
before_save { |user| user.email = email.downcase }
end
When I try to create a new user, I get an error message:
ActiveModel::ForbiddenAttributesError
The following line is highlighted in the registrations controller:
#user = User.new(registration_params)
Witht the additional debug information:
{"utf8"=>"✓", "authenticity_token"=>"CRwY4emBZJXhH7kMNGQZR5H1D3D0IJrHCnBzs5PTE8U=", "user"=>{"email"=>"xxxx#jkjjjkj.com", "password"=>"xxxxxxx", "password_confirmation"=>"xxxxxxx", "first"=>"John", "last"=>"Doe"}, "commit"=>"Create User", "action"=>"create", "controller"=>"registrations"}
Any ideas?
You have defined a method for strong parameters but you cannot just return the params hash - instead you have to specifically whitelist the attributes you wish to pass on to the model.
def registration_params
params.require(:user).permit(:email, :password, :password_confirmation, ...) # etc for the rest of your attributes
end
I need help with the follow problem. I have been looking at similar questions but am still unable to find the solution to the problem. I am currently having this problem.
NoMethodError in Courses#edit
undefined method `model_name' for #Class:0xb5068474
the error seems to be with this line of code.
<%= simple_fields_for #lesson do |f| %>
<%= f.input :lesson_name %>
<%end%>
The lesson database is link to the course database, where course has_many lessons and lesson belongs_to course. I think that the problem may be due to my controller code. I am relatively new and not very sure about how to go about solving this problem.
I am able to go to create page to create that relation but nothing else is saved inside the database but the id of course and lesson. However, when i go to the edit page for course, this error pops out.
courses_controller.rb
class CoursesController < ApplicationController
before_action :set_course, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, :except => [:show,:index]
# GET /courses
# GET /courses.json
def index
#courses = Course.all
end
# GET /courses/1
# GET /courses/1.json
def show
end
# GET /courses/new
def new
#course = Course.new
#lesson = #course.lessons.build
end
# GET /courses/1/edit
def edit
#course = Course.find(params[:id])
#lesson = #course.lessons
end
# POST /courses
# POST /courses.json
def create
#course = Course.new(course_params)
#course.lessons.new(lesson_params)
respond_to do |format|
if #course.save
format.html { redirect_to #course, notice: 'Course was successfully created.' }
format.json { render action: 'show', status: :created, location: #course }
else
format.html { render action: 'new' }
format.json { render json: #course.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /courses/1
# PATCH/PUT /courses/1.json
def update
respond_to do |format|
if #course.update(course_params)
#course.lesson.update_attributes(lesson_params)
#course.staff_ids=params[:course][:staff_ids]
format.html { redirect_to #course, notice: 'Course was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #course.errors, status: :unprocessable_entity }
end
end
end
# DELETE /courses/1
# DELETE /courses/1.json
def destroy
#course.destroy
respond_to do |format|
format.html { redirect_to courses_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_course
#course = Course.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def course_params
params.require(:course).permit(:course_code, :course_name, :year_of_study, :discipline, :Acad_unit, :cohort_size, :remark)
end
def lesson_params
params.require(:lesson).permit(:lesson_type, :lesson_name, :num_lesson, :frequency)
end
end
lesson.rb
class Lesson < ActiveRecord::Base
belongs_to :course
end
course.rb
class Course < ActiveRecord::Base
validates_presence_of :course_code, :course_name
validates_uniqueness_of :course_code, :course_name
validates :year_of_study, :Acad_unit, :cohort_size, :numericality => { :greater_than => 0}
has_and_belongs_to_many :staffs, join_table: :scheduleCourse
has_many :lessons, dependent: :destroy
end
Please give me some advise. Thanks in advance
The error that you get:
undefined method `model_name` for #Class:0xb5068474
Means that simple_fields_for method is doing something like #lesson.class.model_name, which is ok when object you pass (#lesson) is an instance of ActiveRecord::Base, but in edit action you define #lesson
#lesson = #course.lessons
As a relation, so it is not one Lesson instance, it is internal ActiveRecord object for storing relations. If for instance you call first on it:
#lesson = #course.lessons.first
This should work. Or you can iterate through collection of lessons in view to create form for each one of them, it depends on what you want to do.
I am getting an error that is particularly frustrating.
I am trying to create a 'task' that has a user ID associated with it. however when I go to create a new task in the local host I receive the following error message NoMethodError in TasksController#new
undefined method `tasks' for #
Git repo: https://github.com/BrianLobdell/emailtest
Error:
Here is my tasks controller
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
# GET /tasks
# GET /tasks.json
def index
#tasks = Task.all
end
# GET /tasks/1
# GET /tasks/1.json
def show
end
# GET /tasks/new
def new
#task = current_user.tasks.build
end
# GET /tasks/1/edit
def edit
end
# POST /tasks
# POST /tasks.json
def create
#task = current_user.tasks.build(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render action: 'show', status: :created, location: #task }
else
format.html { render action: 'new' }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
Even if you have a belongs_to association in your Task model, you need to have the matching has_many in the User model for the current_user.tasks method to work.
All you need to do is
class User < ActiveRecord::Base
# ...
# ...
has_many :tasks
end
In a Rails 4 app -- I am getting this error when trying to create a simple User in my console.
RuntimeError:
Password digest missing on new record
My model, controller, and schema looks like:
class User < ActiveRecord::Base # User.rb
has_secure_password
end
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to root_path, notice: "Thank you for signing up!"
else
render "new"
end
end
private
def user_params
params.require(:user).permit(:email, :name, :password, :password_confirmation)
end
end
create_table "users", force: true do |t| #db/schema.rb (edited for brevity)
t.string "email"
t.string "name"
t.text "password_digest"
t.datetime "created_at"
t.datetime "updated_at"
end
I am using postgresql, and am not sure if this is a bug, or if I have missed something simple.
Thanks,
In Rails 4 all of the attributes are mass assigned by default so you don't need to use attr_accesible. Now you have to state which ones you want to protect. you would write it like this
attr_protected :admin
The error that you are getting gets raised when password_digest is blank. It probably has something to do with your attr_accesor:. Can I see your view?
I had exact the same problem but that part here solved my problem. The password_confirmation could not be stored because it was not a permit parameter
def user_params
params.require(:user).permit(:name, :password_digest, :password, :password_confirmation)
end
I did it in rails 4:
for use "has_secure_password" you have to use the parameter password_digest
Schema Information = name :string, password_digest :string
class User < ActiveRecord::Base
has_secure_password
validates :name, presence: true, uniqueness: true
validates_presence_of :password, :on => :create
end
and the controller
def user_params
params.require(:user).permit(:name, :password_digest,
:password, :password_confirmation)
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to users_url, notice: "User #{#user.name} was successfully created.'"}
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end