user3412678
user3412678

Reputation: 11

RoR Active Record undefined method

That is the error im getting:
undefined method `attr_accessible' for #

after following a tutorial, my code is:

User.rb:

 class User < ActiveRecord::Base

   attr_accessible :email, :password, :password_confirmation

   attr_accessor :password
   before_save :encrypt_password

   validates_confirmation_of :password
   validates_presence_of :password, :on => :create
   validates_presence_of :email
   validates_uniqueness_of :email

users_conroller.rb:

   class UsersController < ApplicationController
    def new
    @user = User.new
 end

 def create
   @user = User.new(params[:user])
   if @user.save
     redirect_to root_url, :notice => "Signed up!"
   else
     render "new"
   end

 end
 end

Help please! :( I read somewhere to change one of the js coffee files from coffee to just js and put a script in to allow this to work but it didn’t work for me

Upvotes: 0

Views: 565

Answers (3)

Anuj Dubey
Anuj Dubey

Reputation: 347

attr_accessible is depricated in rails 4. please use user_params instead of attr_accessible. In User.rb

# no attr_accessible

In users_controller.rb

 def create
  @user = User.new user_params
  @user.save
 end

at the end

private
  def user_params
     params.require(:user).permit(:email, :password, :password_confirmation)
  end

Hope this will help!!

Upvotes: 1

Richard Peck
Richard Peck

Reputation: 76784

MVC

To further BroiState's amazing answer, you need to appreciate how Rails works as a framework - MVC:

enter image description here

MVC is one of the core aspects of Rails - it's how your data is processed & shown on the screen. The problem for many people is they don't realize the value of this system, and consequently don't realize how to get Rails to work as they require.

When you call data from your system, you're basically using the Model aspect of the framework - the ability to call the data. The problem is that since Rails 3 & Rails 4 handle this differently, you're receiving the error as you're trying to access a function / method which simply doesn't exist.

--

Rails

In the sense of Rails, you have to appreciate that every time you call your data from the model, it will do so by compiling the relative attributes from the database.

Although you can access as much data as you need, Rails has some stringent methods to prevent mass assignment -- the ability for someone to populate attributes without being part of your application's flow.

The way to do this is to "white list" different attributes. Rails 3 did this with attr_accessible, whilst Rails 4 adopted the strong_params pattern:

With this plugin Action Controller parameters are forbidden to be used in Active Model mass assignments until they have been whitelisted. This means you'll have to make a conscious choice about which attributes to allow for mass updating and thus prevent accidentally exposing that which shouldn't be exposed.

The big difference here being that in Rails 4, you can access all the attributes you need from your model (the white listing is done when you submit data); whilst in Rails 3, you can only define the attributes accessed with the attr_accessible directive.

Simply, here's what you have to do:

#app/models/user.rb
class User < ActiveRecord::Base
  # NO attr_accessible
end

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   def new
      @user = User.new
   end

   def create
      @user = User.new user_params
      @user.save
   end

   private

   def user_params
      params.require(:user).permit(:x, :y, :z)
   end
end

Upvotes: 1

BroiSatse
BroiSatse

Reputation: 44715

TL;DR:

This method is not defined in rails 4. Remove it from your models and update your controller so it reads like:

class UsersController < ApplicationController
  def new
    @user = User.new
   end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to root_url, :notice => "Signed up!"
    else
      render "new"
    end
  end

  private

  def user_params
    params.require(:user).allow(:email, :password, :password_confirmation)
  end
end

Explanation:

attr_accessible is a method used in rails 3 to limit an access to certain params. Reason behind it was, that most controller 'create' or 'update' actions looks like:

@model.assign_attributes(params[:model])

Since params has been sent by the user, it might contain anything, including the fields we definitively don't want them to be able to change (like admin: true).

Rails 3 solved that by saying, that only the attributes marked with attr_accessible can be mass assigned, i.e. if a user tries to pass an extra param :admin it will be rejected by assign_attributes method (which is used internally in new, create etc.).

Now, this was not the best idea - there are certain situations when we want them to be able to set some params depending on the context, so for example if user creating the record is in fact an admin he can nominate another user to be admin. Hence, this security logic has been moved from the model to the controller and is known as strong attributes. You can see it uses in the solution at the top (user_params method). This way is much more secure and harder to be misused.

Upvotes: 3

Related Questions