How can I properly configure rails 3 nested attributes - ruby-on-rails

I have 2 models. Member and Survey
member.rb as follows
Class Member < ActiveRecord::Base
has_one :survey, :dependent => :destroy
accepts_nested_attributes_for :survey
attr_accessible :fname,:lname, :address, :city, :state, :zip, :email, :phone, :phone_alt, :e_contact, :e_contact_phone, :physician, :physician_phone, :chiropractor, :chiropractor_phone, :password, :password_confirmation, :remember_me, :survey_attributes
end
survey.rb as follows
Class Survey < ActiveRecord::base
belongs_to :member
end
however, whenever I try to create the member with the survey attributes I receive
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: surveys
I am testing this via the console.

With a has_one association the accessible call should read:
attr_accessible :survey_attributes
The params you're posting need to be nested, like so:
params = { :member => { :name => 'Jack', :survey_attributes => { :attribute => 'value' } } }
In the form make sure that you're building the nested relationship correctly, ie. you must use:
= form_for #member do |f|
...
= f.fields_for :survey do |s|
...
If you have those things setup like so it should work. If this isn't catching your error then please show a log of what you're trying in the console and isn't working.
See #accepts_nested_attributes_for in the Rails API for more info.

Related

Upgrading attr_accessible from Rails 3 to Rails 4

I'm trying to systematically upgrade from rails 3 to rails 4 and all of my 25 models are based on attr_accessor! So before getting into that can anyone provide me a simple example on how to do this. I've read the documentation and other topics but it's not clear on how to do it since this is my first upgrade Rodeo.
class Settings < ActiveRecord::Base
image_accessor :favicon
attr_accessible :company_name, :show_hot_jobs, :show_students, :subheading, :show_testimonials, :show_on_boarding, :max_concurrent_applications
attr_accessible :image_uid, :max_concurrent_application_groups
attr_accessible :primary_color, :white_color, :gray_color, :opacity, :locale, :lang_nl, :lang_fr, :lang_de, :lang_en, :privacy_page
attr_accessible :show_evp, :show_contact_person, :show_jobs_for_you
attr_accessible :favicon, :favicon_uid, :remove_favicon, :retained_favicon
attr_accessible :home_url, :show_correspondence, :show_appointment
attr_accessible :sliderone_uid, :slidertwo_uid, :sliderthree_uid, :sliderfour_uid, :sliderfive_uid
attr_accessible :sliderone_link, :slidertwo_link, :sliderthree_link, :sliderfour_link, :sliderfive_link
attr_accessible :sliderone_testoverview, :slidertwo_testoverview, :sliderthree_testoverview, :sliderfour_testoverview, :sliderfive_testoverview
attr_accessible :sliderone_page, :slidertwo_page, :sliderthree_page, :sliderfour_page, :sliderfive_page
validate :any_lang_present?
validates :max_concurrent_applications, :numericality => { :greater_than_equal_to => 1 }
validates :max_concurrent_application_groups, :numericality => { :greater_than_equal_to => 1 }
# Fav Icon Validation
validates_property :ext, of: :favicon, :in => ['ico', 'png', 'gif']
has_paper_trail
has_many :setting_translations, :foreign_key => :setting_id
accepts_nested_attributes_for :setting_translations, :allow_destroy => true, :reject_if => :all_blank
attr_accessible :setting_translations_attributes, :allow_destroy => true
translates :subheading, :company_name, :image_uid, :home_url, :sliderone_uid, :slidertwo_uid, :sliderthree_uid, :sliderfour_uid, :sliderfive_uid
translates :sliderone_link, :slidertwo_link, :sliderthree_link, :sliderfour_link, :sliderfive_link
translates :sliderone_testoverview, :slidertwo_testoverview, :sliderthree_testoverview, :sliderfour_testoverview, :sliderfive_testoverview
translates :sliderone_page, :slidertwo_page, :sliderthree_page, :sliderfour_page, :sliderfive_page
attr_accessible can be converted like so:
From
class Settings
attr_accessible :home_url
accepts_nested_attributes_for :setting_translations
end
class SettingTranslation
attr_accessible :etc
end
To
class SettingsController
def create
#settings = Settings.new(settings_params)
# ...
end
private
def settings_params
params.require(:settings).permit(
:home_url,
:setting_translations_attributes => [:id, :_destroy, :etc]
)
end
end
Note, you have to include :_destroy if you want to allow destroy on that model (:allow_destroy => true), and you have to include all attributes that should be accessible from any nested attributes. Though you remove attr_accessible when you've permitted, you do not remove accepts_nested_attributes_for.
Just remove attr_accessible from model. and add permit params according to need in controller.
like below :
class SupportTicketsController < ApplicationController
def create
#support_ticket = SupportTicket.create(house_params)
......
end
private
def house_params
params.require(:support_ticket).permit(:subject, :message, ....)
end
end
and if you don't want to make this much changes then add "protected_attributes" gem https://github.com/rails/protected_attributes in your gemfile And everything would work as before.

Ruby on Rails through Heroku object associations :belongs_to :has_many

Real newb question here: I've got courses
class Course < ActiveRecord::Base
attr_accessible :name, :number
has_many :posts
validates :name, presence: true
validates :number, presence: true
validates :number, :format => { :with => /\A\d\d[-]?\d\d\d\z/}
end
and I've got posts
class Post < ActiveRecord::Base
attr_accessible :comments, :course_id, :difficulty, :enjoyability, :hours, :professor, :ranking, :semester, :usefulness
belongs_to :course
end
Almost everything I have was auto-generated by Rails. There are a couple of things I try to do that I can't get to work:
When I "show" a course, I want to show each post associated with that course. However, everything I've tried has given me an error.
After even entering one post into the database (heroku forced me to use PostgreSQL) the index form no longer renders.
I'm almost positive I'm missing something with my associations between them. Does anybody have any ideas as to what I'm doing wrong?
You may get all posts through Course instance:
#course = Course.find(params[:id])
#posts = #course.posts

can't convert symbol into integer error when saving user

So here is my issue. I have been working with users I created at the beginning of my project for a month now. Today I switched from sqllite to sqlserver to meet client requirements and when I went to use my registration form to create a new user I got the following error:
can't convert Symbol into Integer
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"51nF50CYGNqz3N4o7TUYSyWeTadulXojQBPqERjvlcY=",
"user"=>{
"email"=>"test#blizzardlabs.com",
"login"=>"bgarrison",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]",
"profile_attributes"=>{
"prefix"=>"",
"first_name"=>"Bill",
"last_name"=>"Garrison",
"suffix"=>"",
"birthday"=>"1983-06-01",
"phone_numbers_attributes"=>{
"0"=>{
"info"=>"1234567890",
"label"=>"Cell"
}
}
}
},
"commit"=>"Register"}
I have a feeling that at some point I messed up the registration process but I can't for the life of me figure out where. User-> has_one profile-> has_many phone_numbers.
User Controller:
def create
#user = User.new(params[:user])
if #user.save
#profile = #user.profile
flash[:notice] = "Your account has been created."
redirect_to(#user)
else
flash[:notice] = "There was a problem creating you."
render :action => :new, :layout => 'logged_out'
end
end
User Model:
class User < ActiveRecord::Base
# Accessible attributes
attr_accessible :login,
:email,
:password,
:password_confirmation,
:profile_attributes,
:active
# Associations
has_one :profile, dependent: :destroy, autosave: true
# Allows for a profile hash in user creation (stored in :profile_attributes)
accepts_nested_attributes_for :profile
Profile Model:
class Profile < ActiveRecord::Base
# Accessible Attributes
attr_accessible :birthday,
:company_id,
:first_name,
:last_name,
:prefix,
:suffix,
:phone_numbers_attributes,
:addresses_attributes
# Model Associations
has_many :phone_numbers, :as => :contactable, :class_name => "PhoneNumber", autosave: true
accepts_nested_attributes_for :phone_numbers, allow_destroy: true, reject_if: :all_blan
Any help would be appreciated. Thanks!
Update:1 Also, I have tested some and realized if I leave out the phone number then it works.....if I then update using the same form and add a phone number everything works fine.
Nested attributes should be passed in as Array:
"user"=>{
"email"=>"test#blizzardlabs.com",
"login"=>"bgarrison",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]",
"profile_attributes"=>[
{
"prefix"=>"",
"first_name"=>"Bill",
"last_name"=>"Garrison",
"suffix"=>"",
"birthday"=>"1983-06-01",
"phone_numbers_attributes"=>{
"0"=>{
"info"=>"1234567890",
"label"=>"Cell"
}
}
}
]
}
So, after a couple days of banging my head against the wall I have finally figured this out. However to understand it I need to explain my model's a bit better.
Basically, from above you can see that a User has a profile which has many phone_numbers and addresses through a polymorphic association (:as => :contactable ). However, contactable is actually a base class called ContactInformation which uses STI to contain contactable information of all types.
At one point I decided that having 4 extra fields for addresses was cluttering up the STI relationship but I still wanted to keep it. My solution was to serialize all those fields into the "info" field of ContactInformation. Right now, phone numbers only have "number" as a field that is serialized and stored into "info" but if I ever want to seperate it out into "area code" "extension" etc the implementation will be simple.
This leads to the problem. On my registration form I was using label / info for my phone_number fields instead of label / number. I had edited my edit form but not my new form (yes i know they should be the same one but I have a special ajax form for editing).
Here is the code for ContactInformation / PhoneNumber / Address
class ContactInformation < ActiveRecord::Base
attr_accessible :contactable_id, :contactable_type, :info, :label, :type
belongs_to :contactable, :polymorphic => true
end
class PhoneNumber < ContactInformation
attr_accessible :number
stash :number, in: :info
#----------------------------------Validations--Start-------------------------
validates :number, presence: true
#----------------------------------Validations--End---------------------------
end
class Address < ContactInformation
attr_accessible :street_address, :city, :state, :postal
stash :street_address, :city, :state, :postal, in: :info
#----------------------------------Validations--Start-------------------------
validates :street_address, :city, :state, :postal, presence: true
#----------------------------------Validations--End---------------------------
end

Rails 3 association error: undefined method

I've been puzzling over this for quite some time now and can't figure it out.
I've got 2 models:
class Vehicle < ActiveRecord::Base
attr_accessible :year, :capacity,
:size, :body, :model_id, :maker_id, :parameters_attributes
validates :year, numericality: { greater_than: 1900 }
validates :year, :capacity, :size, :body, presence: true
belongs_to :model
belongs_to :maker
has_many :parameters
accepts_nested_attributes_for :parameters
end
and
class Parameter < ActiveRecord::Base
attr_accessible :tag, :value
validates :tag, :value, presence: true
belongs_to :vehicle
end
in new vehicle view i've got:
= form_for [:admin, #vehicle], html: { multipart: true } do |f|
=# some other stuff in between
= f.text_field :value, size: 4
I get this error
undefined method `value'
Just can't seem to get it working. Help, anyone?
EDIT
routes.rb
resources :vehicles
resources :parameters
resources :makers do
resources :models
end
If you are using nested form, you should have something like
f.fields_for :parameters do |parameter|
and than:
parameter.text_field :value, size: 4
Also, remember to create the some parameters in the controller, for example:
def new
#vehicle = Vehicle.new
2.times { #vehicle.parameters.build } #it will create 2 parameters
...
end
f refers to #vehicle, it seems only Parameter bears this field. That's why it fails.
Sidenotes:
In Vehicle you have accepts_nested_attributes_for :parameters but you don't have parameters_attributes in the attr_accessible, can't be good.
If you want to call the relationship in the form consider using fields_for
Ok, I've made a mess of things.
Firstly I've been trying to
def new
#vehicle = #vehicle.parameters.build
end
hence the error undefined method. After a while I got to the correct syntax, which is the one gabrielhilal added after a while.
def new
#vehicle = Vehicle.new
#vehicle.parameters.build
end
No matter ;) Still had problems, because after clicking "create" he wouldn't add records in the database. Turned out that I've set the validates presence: true for tag, but didn't assign any value to it. After fixing that, it worked like a charm. Thanks a lot for all the help.
On to the next puzzle.

ActiveModel::MassAssignmentSecurity::Error in CustomersController#create (attr_accessible is set)

In my controller, I've got error when create action and try create model [can't mass-assignment], but
in my spec, my test of mass-assignment model its pass!?!
My Model:
class Customer < ActiveRecord::Base
attr_accessible :doc, :doc_rg, :name, :birthday, :name_sec, :address, :state_id, :city_id, :district_id,
:customer_pj, :is_customer, :segment_id, :activity_id, :person_type, :person_id
belongs_to :person , :polymorphic => true, dependent: :destroy
has_many :histories
has_many :emails
def self.search(search)
if search
conditions = []
conditions << ['name LIKE ?', "%#{search}%"]
find(:all, :conditions => conditions)
else
find(:all)
end
end
end
I`ve tired set attr_accessible in controller too, in my randomized way.
the Controller:
class CustomersController < ApplicationController
include ActiveModel::MassAssignmentSecurity
attr_accessible :doc, :doc_rg, :name, :birthday, :name_sec, :address, :state_id, :city_id, :district_id, :customer_pj, :is_customer
autocomplete :business_segment, :name, :full => true
autocomplete :business_activity, :name, :full => true
[...]
end
The test, my passed test
describe "accessible attributes" do
it "should allow access to basics fields" do
expect do
#customer.save
end.should_not raise_error(ActiveModel::MassAssignmentSecurity::Error)
end
end
The error:
ActiveModel::MassAssignmentSecurity::Error in CustomersController#create
Can't mass-assign protected attributes: doc, doc_rg, name_sec, address, state_id, city_id, district_id, customer_pj, is_customer
https://github.com/megabga/crm
1.9.2p320
Rails 3.2
MacOS
pg
my bad, in my controller its setting an oldest class. Then old class don`t have attributes passing in parameters. Sorry!

Resources