Devise and ActiveModel::MassAssignmentSecurity::Error - ruby-on-rails

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|

Related

Rails 4 - Polymorphic Association - Nested Attributes not showing in form

I am building a login system that has two users, buyer and seller, in Rails 4.0.4.
For auth I am using the Devise gem: https://github.com/plataformatec/devise
To create a new buyer I use the route buyer/new. However, the fields for the user do not show in the view. I also using debug to show #buyer.user in the view and it has been created. But when I call f.fields_for #buyer.user do |u| the loop is never entered.
Any ideas of why this is? Also, the polymorphic associations seem to be working in the rails console.
Buyer Controller:
# GET /buyers/new
def new
#buyer = Buyer.new
#buyer.build_user
end
Buyer Model
class Buyer < ActiveRecord::Base
has_one :user, as: :role
accepts_nested_attributes_for :user
end
Buyer/new View
<%= form_for(#buyer) do |f| %>
....
<div class="field">
<%= debug(#buyer.user) %>
<% f.fields_for #buyer.user do |u| %>
<%= u.text_field :email %>
<% end %>
</div>
User Model
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :role, polymorphic: true
Shouldn't you have an = on the fields_for? http://rubydoc.info/docs/rails/ActionView/Helpers/FormHelper:fields_for
E.G.
<%= f.fields_for #buyer.user do |u| %>

Rails 4 - Access attributes of nested model in form

I have Account model which have a has_many relationship with User model:
class Account < ActiveRecord::Base
has_many :users, -> { uniq }
accepts_nested_attributes_for :users
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :confirmable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :account
I added avatar attribute to User model using paperclip.
I want each user to have access to the common account settings, and inside it having the possibility to upload his/her own avatar.
I use simple_form so I tried this:
<%= simple_form_for current_account, :html => { :multipart => true } do |f| %>
<%# here come account settings %>
<%= f.input :time_zone, :label => t(".timezone"),
:
:
<%# here I need to access current user attributes %>
<%= f.simple_fields_for :user, current_account.users.first do |user_form| %>
<%= user_form.file_field :avatar, :error => false %>
<% end %>
<% end %>
First problem:
I need some logic to access current_user instead of current_account.users.first. Since there is a superadmin which can access all accounts, use current_user is not enough.
Second (and bigger) problem:
I added in my controller the avatar parameter to the whitelist:
def allowed_params
params.require(:account).permit(:time_zone, :logo, :description, user: [:avatar])
end
When I try to update my model:
if current_account.update(allowed_params)
I get this error:
unknown attribute: user
I also tried:
params.require(:account).permit(:language, :time_zone, :logo, :description, :user_attributes => [:avatar])
and:
params.require(:account).permit(:language, :time_zone, :logo, :description, :users_attributes => [:avatar])
(in plural)
but since I use ActionController::Parameters.action_on_unpermitted_parameters = :raise I get:
found unpermitted parameters: user
It must be something very easy, some help please?
Ok, got it!!
The problem is the one-to-many relationship and the way I tried to access a single instance of user. The correct way to do it is:
<% current_account.users.each_with_index do |user, index|%>
<%= f.simple_fields_for :users, user do |user_form| %>
<%= user_form.file_field :avatar, :error => false %>
<% end %>
<% end %>
As you can see, the iteration should be done over the relation, and only when having a
single instance "in hand" we can user the simple_fields_for.
Also, notice that the first parameter passed to simple_fields_for is :users and not :user, since this is a one-to-many relationship.

Rails Devise registration with an additional model

I've searched for about an hour now and found an immense amount of questions describing how to add fields to the Devise user model. However I couldn't find any that explain in a clear way how to add one or multiple models to the registration process.
At registration I want the user to fill out an e-mailaddress, password and in addition my client model, company model and address model (so I have all the information the webapplication needs to run properly).
My models are like this
user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :client
belongs_to :client
end
client.rb
class Client < ActiveRecord::Base
attr_accessible :bankaccount, :email, :logo, :mobile, :phone, :website
has_many :users
has_one :company
has_one :address
accepts_nested_attributes_for :company, :address
end
I think the only way to do this is to create my own RegistrationsController so I can do #client = Client.new and then do this in my view:
<%= f.simple_fields_for #client do |ff| %>
<%= f.simple_fields_for :company do |fff| %>
<% field_set_tag t(:company) do %>
<%= ff.input :name %>
<% end %>
<% end %>
<%= f.simple_fields_for :address do |fff| %>
//address inputs
<% end %>
<% end %>
<fieldset>
<legend><%= t(:other) %></legend>
// other inputs
</fieldset>
<% end %>
The reason I need it to work this way is because I have multiple users who can represent the same client (and thus need access to the same data). My client owns all the data in the application and therefor needs to be created before the application can be used.
Okay, it took me about 8 hours but I finally figured out how to make it work (if someone has a better/cleaner way of doing this, please let me know).
First I've created my own Devise::RegistrationsController to properly build the resource:
class Users::RegistrationsController < Devise::RegistrationsController
def new
resource = build_resource({})
resource.build_client
resource.client.build_company
resource.client.build_address
respond_with resource
end
end
After that I just needed to adjust config/routes.rb to make it work:
devise_for :users, :controllers => { :registrations => "users/registrations" } do
get '/users/sign_up', :to => 'users/registrations#new'
end
Also I had an error in my devise/registrations/new.html.erb. It should have been f.simple_fields_for :client instead of f.simple_fields_for #client.
Now it properly creates all the objects for the nested attributes and automatically saves it when saving the resource.

Controller not creating with 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?
From my experience with Rails, you can't expect the relation to be made that way. Try something like this.
def create
#organization = Organization.build(params[:organization])
#organization.save
current_user.organizations << #organization
end
You might alternatively keep your code as-is, but save current_user instead of #organization.
def create
#organization = current_user.organizations.build(params[:organization])
current_user.save
end

Rails 3 - Devise nested form giving mass assignment error

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.

Resources