ActiveModel::ForbiddenAttributesError - Rails4 - ruby-on-rails-4

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

Related

Fliendly_ID - URL not being displayed

I am new to ROR and working on a small project. Recently I added the friendly ID gems and followed the instruction on the documentation. But I can't seem to get the URL working. I added the friendly id to communities model which is basically your posts model.
Route code:
class Community < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: [:slugged, :history]
validates :title, :length => { :minimum => 5 }
has_attached_file :post_image, :styles =>
{ :medium => "300x300>", :thumb => "100x100>", :large => "1280x720", :headline => "1280x720"}
validates_attachment_content_type :post_image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
belongs_to :member
has_many :comments
scope :newest_first, lambda { order("communities.created_at DESC")}
scope :without_community, lambda{|community| community ? {:conditions => ["community.id != ?", #community.id]} : {} }
# def to_param
# "#{id}-#{title.parameterize}"
# end
end
I even tried the to_param to get the URL's. But nothing seems to work.
Controller code:
class CommunitiesController < ApplicationController
before_action :set_community, only: [:show, :edit, :update, :destroy]
layout "community"
before_filter :authenticate_member!, except: [:index, :show]
require 'will_paginate/array'
# GET /communities
# GET /communities.json
def index
#communities = Community.newest_first.friendly.where(params[:id]).paginate(page: params[:page], per_page: 9)
end
# GET /communities/1
# GET /communities/1.json
def show
#communities = Community.newest_first.friendly.where(params[:title]).paginate(page: params[:page], per_page: 5).where('id NOT IN (?)', #community.id)
end
# GET /communities/new
def new
#community = Community.new({:member_id => current_member.id})
end
# GET /communities/1/edit
def edit
end
# POST /communities
# POST /communities.json
def create
#community = Community.new(community_params)
respond_to do |format|
if #community.save
format.html { redirect_to #community, notice: 'Post: #{#community.title.capitalize} was successfully created.' }
format.json { render :show, status: :created, location: #community }
else
format.html { render :new }
format.json { render json: #community.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /communities/1
# PATCH/PUT /communities/1.json
def update
respond_to do |format|
if #community.update(community_params)
format.html { redirect_to #community, notice: 'Post: #{#community.title.capitalize} was successfully updated.' }
format.json { render :show, status: :ok, location: #community }
else
format.html { render :edit }
format.json { render json: #community.errors, status: :unprocessable_entity }
end
end
end
# DELETE /communities/1
# DELETE /communities/1.json
def destroy
#community.destroy
respond_to do |format|
format.html { redirect_to communities_url, notice: 'Post: #{#community.title.capitalize} was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_community
#community = Community.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def community_params
params.require(:community).permit(:name,:post_image, :title, :content, :member_id)
end
end
But If I type the URL like http://localhost:3000/communities/post.title I am able to go directly to the post. That means the slugs have been created and they are working kind of. But I can't seem to get them displayed on the URL.
I have tried many permutation and combinations but nothing seems to work.
Would really appreciate any help. Let me know if there is any other specific code you require.
FYI: Migrations code:
class AddSlugToCommunities < ActiveRecord::Migration
def change
add_column :communities, :slug, :string, limit: 191
add_index :communities, :slug, unique: true
end
end
Friendly_ID migration code:
class CreateFriendlyIdSlugs < ActiveRecord::Migration
def change
create_table :friendly_id_slugs do |t|
t.string :slug, :null => false, limit: 191
t.integer :sluggable_id, :null => false
t.string :sluggable_type, :limit => 50
t.string :scope, limit: 191
t.datetime :created_at
end
add_index :friendly_id_slugs, :sluggable_id
add_index :friendly_id_slugs, [:slug, :sluggable_type]
add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], :unique => true
add_index :friendly_id_slugs, :sluggable_type
end
end
Went deeper into the code and found that slugs were being made. its just that the URL was not being linked properly. Made a few changes to the links to to use slugs instead of :id to get it working.
Thanks anyways #uzaif

Rails Associations appearing 'nil'

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

routing issue passing id rails 4

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.

NoMethodError in Courses#edit undefined method `model_name'

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.

Rails 4 has_secure_password

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