I am a newbie to Ruby and Rails. In my Rails app, I am trying to use Wicked Wizard gem and need some help in Understanding about the cattr_accessor which I have come across in the code
# migration
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
# controller
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'
end
Now my Questions are:
1) what is the difference between the cattr_accessor
and attr_accessor
?
cattr_accessor :form_steps do
%w(identity characteristics instructions)
end
attr_accessor :form_step
2) why two different symbols(:form_steps
, :form_step
) are used as method parameters for cattr_accessor
and attr_accessor
methods respectively?
3) why is a block passed as a parameter to cattr_accessor
method?
First of all, this method is deprecated or moved. Which version do you use, Rails 4 or Rails ?
cattr_accessor
> replaced formattr_accessor(*syms, &blk)
forModule
which is the superclass of the classClass
. I recomend to use attr_accessor, which is just a method to set attributes for the class, it works like a getter or a setter for the class but only works for an instance (in memory), the attribute is saved anywhere.cattr_accessor
is like theattr_*
methods, but for the class level. One thing you wouldn't expect is because it uses a backing@@form_steps
, the value shared between the class and all instances.Api docs:
Defines both class and instance accessors for class attributes.
If a subclass changes the value then that would also change the value for parent class. Similarly if parent class changes the value then that would change the value of subclasses too.
To opt out of the instance writer method, pass instance_writer: false. To opt out of the instance reader method, pass instance_reader: false.
Or pass
instance_accessor: false
, to opt out both instance methods.Also you can pass a block to set up the attribute with a default value.
1)
2) Class variable have a tendency to wander from class to class. @@form_steps class variable can be exposed through inheritance tree.
3) To set which attributes will have this class.
form_steps
and use the
form_steps
attribute inside your current instance Pet (like you do in the methodrequired_for_step?
).