Rails 3 - Devise nested form giving mass assignment error - ruby-on-rails

I know this has been covered a few time on here but I cant seem to solve this error -
WARNING: Can't mass-assign protected attributes: new_order_attributes
This is the nested hash that is trying to be saved -
Parameters: {"utf8"=>"✓","authenticity_token"=>"UNKZf7zvlyReHSCbMRRl+9y+F5/2YF8Rf64Wm9O9xyo=", "user"=>{ "new_orders_attributes"=>[{"plan_id"=>"2", "price_id"=>"2222"}], "first_name"=>"Alex", "last_name"=>"Handley", "email"=>"alex#s.co.uk", "job_title"=>"Programmer", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}
The user data is saved but the order is not saved.
Models
User
devise :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :location, :country, :job_title, :company, :parent_id,:first_name,:last_name,:subscription_type,
:orders, :plan_id, :user_id, :price_id
has_many :orders
has_many :plans, :through => :orders
accepts_nested_attributes_for :orders, :plans
Orders
class Order < ActiveRecord::Base
belongs_to :plan
belongs_to :user
end
Plans
has_many :orders
has_many :users, :through => :orders
Rails -v - 3.0.3
Nested Form
<% prefix = "user[new_orders_attributes][]" %>
<%= fields_for prefix, #user.orders do |order_form| %>
<%= order_form.hidden_field :plan_id, :value => 2 %>
<%= order_form.hidden_field :price_id, :value => 2222 %>
<% end %>
Thanks, Alex

Try adding orders_attributes to the attribute list in the attr_accessible statement.

Related

Usage of f.collection_select in a has_many :through relation

Let me explain my problem,
what I'm trying to do is displaying a dropdown list of teams (one of my models) of which the current user is a member, to allow him to select which of his teams he would like to join a tournament (another model). Here's what I was thinking of doing (and failed doing so):
in the show view of a selected tournament
<%= form_for #new_team, :url => join_tournament_path do |f| %>
<%= f.collection_select :team_id, current_user.user_teams, team ids of user teams?, user teams names parameter i guess, include_blank: true %>
<%= f.submit %>
<% end %>
show action in the controller
def show
#tournament = Tournament.find(params[:id])
#new_team = #tournament.teams_in_tournaments.build
end
I'd like the form to send the the tournaments id along with the team id of the team selected by the user to my custom "join" controller action which would save the whole thing.
Hopefully someone could point me in a direction of a solution, because I think I don't really understand how the f.collection_select works (and the documentation wasn't really helpful in my case)
(excuse my english by the way)
EDIT:
My models and relationships:
Team:
class Team < ActiveRecord::Base
has_many :user_teams
has_many :users, :through => :user_teams
has_many :teams_in_tournaments
has_many :tournaments, :through => :teams_in_tournaments
belongs_to :team_leader, class_name: "User"
end
User:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :user_teams
has_many :teams, :through => :user_teams
end
Tournament:
class Tournament < ActiveRecord::Base
has_many :teams_in_tournaments
has_many :teams, :through => :teams_in_tournaments
belongs_to :organizer, class_name: "User"
end
UserTeam:
class UserTeam < ActiveRecord::Base
belongs_to :user
belongs_to :team
validates :team_id, :uniqueness => { :scope => :user_id }
end
TeamsInTournament:
class TeamsInTournament < ActiveRecord::Base
belongs_to :tournament
belongs_to :team
validates :team_id, :uniqueness => { :scope => :tournament_id }
end
You are halfway there, the only missing thing is to add id's and names of the objects you want outputted in the <option> elements
In your case it would be something like this:
<%= form_for #new_team, :url => join_tournament_path do |f| %>
<%= f.collection_select :team_id, current_user.user_teams, :id, :name, include_blank: true %>
<%= f.submit %>
<% end %>

accepts_nested_attributes_for with belongs_to polymorphic devise

I have 3 models and this associations for them
class User < ActiveRecord::Base
# devise modules here
attr_accessible :email, :password, :password_confirmation, :remember_me, :rolable_id, :rolable_type
belongs_to :rolable, :polymorphic => true
end
class Player < ActiveRecord::Base
attr_accessible :age, :name, :position
has_one :user, :as => :rolable
end
class Manager < ActiveRecord::Base
attr_accessible :age, :name
has_one :user, :as => :rolable
end
I'm out of the box from rails way to put accepts_nested_attributes_for :rolable on user model and In this accepts_nested_attributes_for with belongs_to polymorphic question I found some solutions for it but all solution not works for me. All solutions, always the same error when I try to create a user
Processing by RegistrationsController#create as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"WKCniJza+PS5umMWCqvxFCZaRVQMPZBT4nU2fl994cU=", "user"=>{"email"=>"john#email.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "rolable_type"=>"manager", "rolable"=>{"name"=>"john", "age"=>"24"}}, "commit"=>"Sign up"}
Completed 500 Internal Server Error in 143.0ms
NoMethodError (undefined method `primary_key' for ActiveSupport::HashWithIndifferentAccess:Class):
app/controllers/registrations_controller.rb:13:in `new'
app/controllers/registrations_controller.rb:13:in `create'
My mistake, I'm use nested form
<%= f.fields_for :rolable do |rf| %>
....
<% end %>
change to
<%= f.fields_for :rolable_attributes do |rf| %>
....
<% end %>
for polymorphic association you have to maintain generic model Roll like
class User < ActiveRecord::Base
# devise modules here
attr_accessible :email, :password, :password_confirmation, :remember_me
has_many :rolls, :as => :rolable
end
class Player < ActiveRecord::Base
attr_accessible :age, :name, :position
has_many :rolls, :as => :rolable
end
class Manager < ActiveRecord::Base
attr_accessible :age, :name
has_many :rolls, :as => :rolable
end
class Roll < ActiveRecord::Base
attr_accessible :rolable_id, :rolable_type
belongs_to :rolable, :polymorphic=> true
end

Attributes not showing on users#show page

users_controller.rb
class ProfilesController < ApplicationController
before_filter :authenticate_user!
def show
#user = User.find(params[:id]) || User.find(current_user.id)
#questions_for_about = #user.questions.for_about.order('id asc')
#questions_for_personality = #user.questions.for_personality.order('id asc')
end
end
user#show.html.erb
<div class="element">
Ethinicity:
<%= #user.ethnicity.present? ? #user.ethnicity.name : "" %>
</div>
<div class="element">
Education:
<span class="select_for_education">
<%= #user.education.present? ? #user.education.name : "" %>
</div>
The user.education.name is just showing the following - Education:
Without showing the users Education in which was chosen on his personal profile using the following select:
<div class="element">
Ethinicity:
<%= best_in_place current_user, :ethnicity_id, :type => :select, collection: Ethnicity.all.map{|e| [e.id, e.name]}, :inner_class => 'education-edit', nil: 'Select Ethnicity' %>
</div>
<div class="element">
Education:
<span class="select_for_education">
<%= best_in_place current_user, :education_id, :type => :select, collection: Education.all.map{|e| [e.id, e.name]}, :inner_class => 'education-edit', nil: 'Select Education' %>
</div>
What am I doing wrong? And how can I get the users education that DOES display on his/her own profile to display in the show page?
Thanks in advanced!
User.rb
class User < ActiveRecord::Base
include PgSearch
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable,
:omniauth_providers => [:facebook, :twitter, :linkedin]
attr_accessible :email, :password, :password_confirmation, :zip, :gender, :remember_me, :first_name, :last_name,
:birthday, :current_password, :occupation, :address, :interests, :aboutme, :profile_image,
:photos_attributes, :age, :education_id, :ethnicity_id, :blurb
has_many :authorizations, :dependent => :destroy
has_many :comments
has_many :events
has_many :photos, as: :attachable
has_many :questions
has_many :sent_messages, class_name: 'Message', foreign_key: :sender_id
has_many :received_messages, class_name: 'Message', foreign_key: :receiver_id
has_one :ethnicity
has_one :education
end
ethnicity.rb
class Ethinicity < ActiveRecord::Base
attr_accessible :name
has_many :users
end
education.rb
class Education < ActiveRecord::Base
attr_accessible :name
has_many :users
end
You're missing belongs_to association for has_many and has_one relation. The belongs_to association definition needs to be defined in the model whose table has the foreign key.
Given your models, although the other way around is imaginable, here is what I think the associations should look like:
# User Model
class User < ActiveRecord::Base
...
belongs_to :ethnicity
belongs_to :education
end
# Ethnicity Model
class Ethinicity < ActiveRecord::Base
attr_accessible :name
has_many :users
end
# Education Model
class Education < ActiveRecord::Base
attr_accessible :name
has_many :users
end

Devise and ActiveModel::MassAssignmentSecurity::Error

I am working on the registration process via devise
I try to save "payments" to a "user" which registers via a formular.
When User choose "bank" from a checkbox, a depending Payment should be also created to the User.
<!-- language: ruby -->
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable
attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name
attr_accessible :payments_attributes
# also tried attr_accessible :payments_attributes, :payments
has_many :payments, :autosave => true
accepts_nested_attributes_for :payments, allow_destroy: false
end
class Payment < ActiveRecord::Base
attr_accessible :method, :paid
attr_accessor :method, :paid
belongs_to :user
end
new.html.erb
<%= f.fields_for :payment do |payment| %>
<div>
<%= payment.radio_button(:method, 'bank') %>
<%= payment.label :bank_transfer %>
<%= payment.radio_button(:method, 'paypal') %>
<%= payment.label :paypal %>
</div>
<% end %>
These are the attributes I wanna set:
my_attributes = {"first_name"=>"Max", "last_name"=>"Mustermann", "password"=>"12345678", "password_confirmation"=>"12345678", "email"=>"max#mustermann.at", "company"=>"ACME INC", "industry"=>{"title"=>"Metall", "oenace"=>"123"}, "payments"=>{"method"=>"bank_transfer", "paid"=>"false"}}
User.new(my_attributes)
# ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: payments
I also tried to add this to the user model:
def after_initialize
self.payments.build if self.payments.blank?
end
Any ideas or suggestions why these params not being saved?
You are trying to assign payments instead of payments_attributes. If this is being returned by fields_for in a view, it is most likely caused by lack of accepts_nested_attributes_for :payments inside your User model.
UPDATE:
you missed 's' in name of your association passed to fields_for. Should be
fields_for :payments do |payment|

Controller not creating association

I've got two models, Users and Organizations, which have a has_many relationship using an assignments table. I have a nested resource form when the user is created, which creates an associated organization just fine. However, when creating an organization, it doesn't associate it with the user.
Here's my relevant Organizations controller code:
def new
#organization = current_user.organizations.build
end
def create
#organization = current_user.organizations.build(params[:organization])
#organization.save
end
And my models:
Organizations Assignments
class OrganizationAssignment < ActiveRecord::Base
belongs_to :user
belongs_to :organization
attr_accessible :user_id, :organization_id
end
Organizations:
class Organization < ActiveRecord::Base
validates :subdomain, :presence => true, :uniqueness => true
has_many :organization_assignments
has_many :people
has_many :users, :through => :organization_assignments
attr_accessible :name, :subdomain
end
Users:
class User < ActiveRecord::Base
has_many :organization_assignments
has_many :organizations, :through => :organization_assignments
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
accepts_nested_attributes_for :organizations
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :organizations_attributes
# attr_accessible :title, :body
end
form view:
= form_for #organization, :html => { :class => 'form-horizontal' } do |f|
- #organization.errors.full_messages.each do |msg|
.alert.alert-error
%h3
= pluralize(#organization.errors.count, 'error')
prohibited this user from being saved:
%ul
%li
= msg
= f.label :name
= f.text_field :name
= f.label :subdomain
= f.text_field :subdomain
.form-actions
= f.submit nil, :class => 'btn btn-primary'
= link_to t('.cancel', :default => t("helpers.links.cancel")), organizations_path, :class => 'btn'
I'm able to associate the organizations fine after the fact in the console, so I'm pretty sure the relationships are set up correctly in the model. Is there anything else I'm missing?

Resources