I have used RESTful techniques to generate a model (in fact, I am using Devise gem, which does that for me), and I have added new fields called first_name and last_name to the model. Migration went fine. I added attr_accessor :first_name, :last_name to the model and expected it would just work. But when I try to mass-assign new instances with Doctor.create({:first_name=>"MyName"}) etc., I am getting errors saying I can't mass-assign protected attributes.
I thought the whole point of using attr_accessor was to get around the protectedness of the fields of a model. Can you help me make sense of this message?
Edit: oh, and by the way the records do not get created either. I thought they should be since this is just a warning, but they are not on the database.
Edit2: here is my model
class Doctor < User has_many :patients has_many :prescriptions, :through=> :patients validates_presence_of :invitations, :on => :create, :message => "can't be blank" attr_accessor :invitations end
and the schema, which doesn't have the first_name and last_name because they are created in the users table, which is the ancestor of doctors. I used single table inheritance.
create_table :doctors do |t| t.integer :invitations t.timestamps end
and this is the migration to change the users table
add_column :users, :first_name, :string add_column :users, :last_name, :string add_column :users, :type, :string
EDIT: here is the seed file. I am not including the truncate_db_table method, but it works.
%w{doctors patients}.each do |m| truncate_db_table(m) end Doctor.create(:invitations=>5, :email=>"[email protected]", :first_name=>"Name", :last_name=>"LastName") Patient.create(:doctor_id=>1, :gender=>"male", :date_of_birth=>"1991-02-24")
Don't confuse attr_accessor
with attr_accessible
. Accessor is built into Ruby and defines a getter method - model_instance.foo # returns something
- and a setter method - model_instance.foo = 'bar'
.
Accessible is defined by Rails and makes the attribute mass-assignable (does the opposite of attr_protected
).
If first_name
is a field in your model's database table, then Rails has already defined getters and setters for that attribute. All you need to do is add attr_accessible :first_name
.
To hack your app together in an insecure way totally unfit for production mode:
Go to /config/application.rb Scroll down towards the end where you'll find
{config.active_record.whitelist_attributes = true}
Set it to false.
EDIT/btw (after 4 months of ruby-intensive work including an 11 week workshop): DHH believes that, for noobies (his words), "up and running" is more important than "very secure".
BE ADVISED: A a lot of experienced rails developers feel very passionate about not wanting you to do this.
UPDATE: 3 years later, another way to do this -- again, not secure, but better than the above solution probably because you have to do it for each model
class ModelName < ActiveRecord::Base column_names.each do |col| attr_accessible col.to_sym end ... end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With