Reputation: 111
I'm creating my own website using Ruby on Rails. One thing that I've failed to comprehend is why and when to use attr:accessors
in place of a permanent column for a model. For instance, let's say that I created a 'posts' model which would have a title, description and some content associated with it. Now should I do rails g model Post title:string description:text content:text
or should I declare them as attr:accessible :title, :description, :content
.
I'm not very experienced in rails, so please bear with me if this sounds too silly to you.
Upvotes: 1
Views: 521
Reputation: 76784
To add to Pardeep
's epic answer, you'll want to look at this RailsCast (RE "virtual attributes"):
attr_accessor
basically creates a setter
& getter
method in the model.
Probably doesn't make any sense; what you have to remember is that each Rails
model is a class. Classes form the backbone of object-orientated programming.
Since Ruby is object orientated, each time you do anything with the language, it expects classes to be invoked & manipulated. The basis of OOP is to load classes into memory & play with them; good write-up here.
In classic OOP, your classes would be hard-coded with a series of attributes:
class Mario
def jump
pos_y + 5
end
def pos_y
# gets y val from the viewport
end
end
This will allow you to send instructions to the program, in turn modifying the class:
@mario.jump
... this should modify the viewport etc in the way you defined within the class.
--
Rails is very similar to the above, except most of the attributes are defined by ActiveRecord;
#app/models/mario.rb
class Mario < ActiveRecord::Base
# attributes from db include height, weight, color etc
end
Rails models allow you to call:
@mario = Mario.find x
@mario.height = "255"
... however, they don't allow you to create attributes which are stored in memory only.
For example...
#app/models/mario.rb
class Mario < ActiveRecord::Base
attr_accessor :grown
end
The above will give you an instance value of grown
, which will allow you to populate this independently of the database.
So say you wanted to...
@mario = Mario.find x
@mario.grown = true if params[:grown]
@mario.height += "150" if @mario.grown
Regarding the difference between attr_accessor
and attr_accessible
, you'll want to look up Rails 3 and mass assignment.
I came into Rails ~ 4.0, so I didn't have to deal with attr_accessible
so much; it was basically the way to permit parameters in Rails 3 models.
In Rails 4/5, you use strong params
in the controller:
#app/controllers/mario_controller.rb
class MarioController < ApplicationController
def create
@mario = Mario.new mario_params
@mario.save
end
private
def mario_params
params.require(:mario).permit(:x, :y, :z)
end
end
Upvotes: 0
Reputation: 3946
You can use attr_accessor
if you need virtual attributes in model.
For eg: In contact us form you need not to see form data, but you need to send that data using email. So you can create attr_accessor
for adding virtual attributes and can also apply validations on that.
class Contact
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :content
validates_presence_of :name
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
validates_length_of :content, :maximum => 500
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
attr_accessible
is to white list of attributes that can be mass assigned in model.
class Comment < ActiveRecord::Base
attr_accessible :user_id, :content
end
def create
#so here params[:comment], have all parameters. But if those params are not in attr_accessible list it will not save it.
# you can try that by remove attr_accessible from model
@comment = Comment.new(params[:comment])
if @comment.save
flash[:notice] = "Successfully created comment."
redirect_to @comment
else
render :action => 'new'
end
end
Comment Form:
<%= form_for @comment do |f| %>
<%= f.error_messages %>
<%= f.hidden_field :user_id, value: current_user.id %>
<p>
<%= f.label :content %><br />
<%= f.text_area :content %>
</p>
<p><%= f.submit %></p>
<% end %>
Happy Coding...
Upvotes: 1