Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

usage of attr_accessor in a rails model class

Excuse me for the noob question.I am a newbie to ruby and rails and Needed some help in Understanding the attr_accessor which I have come across in the code

  create_table "pets", force: :cascade do |t|
            t.string   "name"
            t.string   "colour"
            t.string   "owner_name"
            t.text     "identifying_characteristics"
            t.text     "special_instructions"
            t.datetime "created_at"
            t.datetime "updated_at"
            t.string   "email"
            t.string   "password"
          end

model

 class Pet < ActiveRecord::Base
  has_many :pet_photos
  cattr_accessor :form_steps do
    %w(identity characteristics instructions)
  end

  attr_accessor :form_step
  validates :email, presence: true
  validates :name, :owner_name, presence: true, if: -> { required_for_step?(:identity) }
  validates :identifying_characteristics, :colour, presence: true, if: -> { required_for_step?(:characteristics) }
  validates :special_instructions, presence: true, if: -> { required_for_step?(:instructions) }

  def required_for_step?(step)
    return true if form_step.nil?
    return true if self.form_steps.index(step.to_s) <= self.form_steps.index(form_step)
  end



end

and

      class Pet::StepsController < ApplicationController
        include Wicked::Wizard
        steps *Pet.form_steps

        def show
          @pet = Pet.find(params[:pet_id])
          render_wizard
        end

        def update
          @pet = Pet.find(params[:pet_id])
          @pet.update(pet_params(step))

            if params[:images]

                params[:images].each do |image|
                @pet.pet_photos.create(image: image)
              end
            end

          render_wizard @pet
        end

        private

        def pet_params(step)
          permitted_attributes = case step
                                 when "identity"
                                   [:name, :owner_name]
                                 when "characteristics"
                                   [:colour, :identifying_characteristics]
                                 when "instructions"
                                   [:special_instructions]
                                 end

          params.require(:pet).permit(permitted_attributes).merge(form_step: step)
        end

      end

routes

  PetThing::Application.routes.draw do
          resources :pets, only: [:new, :create, :index, :destroy] do
            resources :steps, only: [:show, :update], controller: 'pet/steps'
          end

          root to: 'pets#index'

1) what I all only know about attr_accessor is, it nothing more than a getter/setter for an object.I do not have a form_step as an attribute of my Pet Model(pets table).But in the model, there is attr_accessor :form_step.How is getter/setter generated to :form_step ?

2) Is :form_step an object of Pet class?

I am not totally understanding the usage of attr_accessor method in Rails model class.

3) Kindly explain me a scenario where I must generate getter/setter for Model attributes (pets table attributes or fields)

eg: attr_accessor :name attr_accessor :colour ..etc

when do we use attr_accessor for model attributes or fields?

like image 255
current_user Avatar asked Dec 05 '17 07:12

current_user


2 Answers

Lets starts with OOPs, basically class is template which defines properties and behavior of its instances i.e. objects.

The rails model also a ruby class. Its properties are being defined by attr_accessor and behaviors are defined by static and instance methods.

Consider a class with attr_accessor

class Animal
      //defines animal properties
      attr_accessor :legs
      //defines animal behavior
      def talk
      end
end

and without attr_accessor

class Animal
      //defines animal properties
      //getter
      def legs
        @legs
      end
      //setter
      def legs=(value)
        @legs = value
      end

      //defines animal behavior
      def talk
      end
end

Both representations are exactly same. The attr_accessor automatically add getter and setter for us and makes the life of developer easier.

Lets answer you questions

  1. Ruby attr_accessor automatically adds these for you as explained earlier.

  2. form_step its a attribute of Pet class and can be accessed as petObj.form_step.

  3. If table is associated/mapped with Model, then you don't have to define columns in tables as attr_accessor, Rails automatically takes care for you. If field or attribute not exists in table, then you need to manually define it as attr_accessor in Model.

I hope this answers your question.

like image 84
Satishakumar Awati Avatar answered Oct 07 '22 17:10

Satishakumar Awati


Part of the Rails' magic is that when you have a class Pet and a table pets, you get the accessors for all the columns in the table for free. It's as if you've declared attr-accessor for all of them, only you don't need to.

In your example, #form_step is not created in the table. But it is declared using attr_accessor. It works just like plain old ruby. This gives you a getter/setter (answer to your Q1).

It's an instance method of Pet class. You call it on a Pet object, like Pet.new.form_step = 5(answer to Q2).

But you can't persist whatever value you assign to #form_step to db. So the answer to Q3 is that you usually do this when you need to pass some messages (i.e. call methods) between your objects, but you don't need to persist them to db.

like image 2
EJAg Avatar answered Oct 07 '22 16:10

EJAg