Controller not creating with association - ruby-on-rails

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

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 %>

What am I doing wrong? [Rails, belongs_to]

Stuck on nested forms..
Order model:
class Order < ActiveRecord::Base
belongs_to :user
accepts_nested_attributes_for :user
end
User mode:
class User < ActiveRecord::Base
has_many :orders, dependent: :destroy
accepts_nested_attributes_for :orders
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Form view:
=form_for #order do |order|
=order.fields_for :user, #order.user do |user|
.row
.col-md-3
.form-group
=user.label :first_name, "Name"
=user.text_field :first_name, :class => "form-control"
.col-md-3
.form-group
=user.label :last_name, "Last name"
=user.text_field :last_name, :class => "form-control"
.col-md-3
=user.label :email, "Email"
=user.text_field :email, :class => "form-control"
.col-md-3
=user.label :telephone, "Phone"
=user.text_field :telephone, :class => "form-control"
.row
.col-md-4.margin-top-15
=order.submit 'Send', :class => 'btn btn-success'
OrdersController:
class OrdersController < ApplicationController
def new
#order = Order.new
if user_signed_in?
user = current_user
else
user = User.new
end
end
def create
#order = Order.new order_attributes
#order.save
end
private
def order_attributes
params.require(:order).permit(:user_id, user_attributes: [:id, :user_id, :user, :first_name, :last_name, :email, :telephone, :password, :password_confirmation])
end
end
So this is what I am trying to do:
User model has devise. I want to create order and assign to it user_id. On submit it tells me "Unpermitted parameter: user". Order model creates its column, but nothing goes to user model.
What am I doing wrong?
Change:
params.require(:order).permit(:user_id, user_attributes: [:id,...
to:
params.require(:order).permit(:user_id, user: [:id,...
Remove :user from :user_attributes.
And I don't think :user_id is necessary.

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.

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