During registration of a new user with Devise, I need to create a new Family object link to this new user at the same time (the user being the head of the family).
My family model:
belongs_to user
My user model:
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :family
has_one :family
accepts_nested_attributes_for :family
In devise/registration/new.html.erb
<%= simple_form_for([resource, Family.new], :as => resource_name, :url => registration_path(resource_name), :html => {:class => 'form-vertical' }) do |f| %>
<%= f.error_notification %>
<%= display_base_errors resource %>
<%= f.input :name, :autofocus => true %>
<%= f.input :email, :required => true %>
<%= f.input :password, :required => true %>
<%= f.input :password_confirmation, :required => true %>
<% f.fields_for :family do |family_form| %>
<p><%= family_form.label :name %></p>
<p><%= family_form.text_field :name %></p>
<% end %>
<%= f.button :submit, 'OK', :class => 'btn-primary' %>
<% end %>
But this is not working, I find a couple of question like this but I did not manage to fix that.
Any idea ?
UPDATE 1
I got the following error:
undefined method `email' for #<Family:0x007f892a12c310>
Family is a model that do not have any email, just a name. I just need to be able to create a new Family object with a name when creating a new user (and link it to the user as well).
UPDATE 2
I have added resource.build_family in my registrations controller. The family object is correctly created and associated to the user (I can display <%= resource.family %> in new.html.erb for debugging), but still no form displayed for the family.
You need the equal sign in the <%=fields_for
<%= f.fields_for :family do |family_form| %>
<p><%= family_form.label :name %></p>
<p><%= family_form.text_field :name %></p>
<% end %>
And in your user model you need to make the :family_attribues accessible and not :family
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :family_attributes
has_one :family
accepts_nested_attributes_for :family
If you're getting undefined method 'email' for #<Model:0x007f892a12c310>:
You need to overwrite Devise::RegistrationsController as described in the docs: https://github.com/heartcombo/devise#configuring-controllers. E.g.
class Users::RegistrationsController < Devise::RegistrationsController
def new
super do |resource|
resource.build_<model>
end
end
end
And you must only specify resource in form_for: simple_form_for(resource, ... instead of simple_form_for([resource, Model.new], ...
Related
Hello people I have some challenges here with devise authentication for users:
I have two models called color and sub_color in my application. the sub_color belongs_to color and color has_many sub_colors.I have already seeded the database with the appropriate data
The challenge; I want a user to be able to chose these in the devise form_for when they are registering as a collection object and the id of the sub_color will be used for identifying a particular user also(a situation where for instance I can sort all the users which cosed blue color). How do I achieve this please?
This is what I have tried but it is not working:
%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :email, required: true, autofocus: true %>
<%= f.input :user_name, required: true %>
<%= f.input :password, required: true, hint: ("# {#minimum_password_length} characters minimum" if #minimum_password_length) %>
<%= f.input :password_confirmation, required: true %>
<%= f.input :first_name, required: true %>
<%= f.label :color_id, "Color" %> <br/>
<%= f.collection_select :color_id, Color.order(:name), :id, :name, include_blank: true%>
<%= f.label :sub_color_id, "Sub Color" %> <br/>
<%= f.grouped_collection_select :sub_color_id, Color.order(:name), :sub_color, :name, :id, :name, include_blank: true%>
<div class="form-actions">
<%= f.button :submit, "Sign up" %>
</div>
model for users:
belongs_to :sub_color
has_one :color, through: :sub_color
devise.......
end
model for sub_color
has_many :users
belongs_to :color
end
model for color
has_many :sub_color
end
This is the error I see on the web browser
NoMethodError in Devise::Registrations#new
[undefined method `color_id' for #<User:0xbacc720>]
Firstly, You need to add color_id and sub_color_id to users table.
Then define association, in user.rb belongs_to :sub_color and in sub_color.rb has_many :users. Same goes with color, user.rb belongs_to :color and in color.rb has_many :users .
Hope that helps!
My app got installation controller and address controller.
Address has_one :installation and Installation belongs_to :address
In my installation view, I got a simple_form inside in other simple_form. Like this:
<%= simple_form_for #installation, class: 'form-horizontal' do |f| %>
<%= f.error_notification %>
<%= f.simple_fields_for #installation.address do |u| %>
<%= u.label :street_address, label: t('address.address_label'), required: true, class: 'col-sm-2 control-label' %>
<%= u.input_field :street_address, class: 'form-control'
%>
So how I can update the two models ?
Can I have two def params ? Likes this:
def installation_params
params.require(:installation).permit(x)
end
def installation_address_params
params.require(:????).permit(y)
end
You can use nested attributes.
Untested, but roughly:
Model:
class Installation < ActiveRecord::Base
belongs_to :address
accepts_nested_attributes_for :address
end
And in your InstallationsController:
params.require(:installation).permit(...,
address_attributes: [:id, ...])
I'm getting a AssociationTypeMismatch Error and I'm not sure where I'm making a mistake. I'm pretty new to Rails so I'm guessing I'm making some silly mistake. I've checked my syntax and compared it against AssociationTypeMismatch Error on Ruby on Rails app
... but I still can't seem to catch the error.
Here's my models
class User < ActiveRecord::Base
attr_accessible :email, :full_name, :password, :password_confirmation, :preference
has_secure_password
validates_uniqueness_of :email
validates_presence_of :full_name
has_one :preference, :dependent => :destroy
accepts_nested_attributes_for :preference
end
class Preference < ActiveRecord::Base
attr_accessible :background_fill, :background_position, :layout
belongs_to :user
end
Here's my controller:
def new
#user = User.new
#user.build_preference
end
def create
#user = User.new(params[:user])
if #user.save
session[:user_id] = #user.id
redirect_to root_url, notice: "Thanks for signing up!"
else
render "new"
end
end
Here's my view:
<%= form_for #user do |f| %>
<% if #user.errors.any? %>
<div class="error_messages">
<h2>There's an error!</h2>
<ul>
<% #user.errors.full_message.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label :full_name %>
<%= f.text_field :full_name, :class => "target", :placeholder => "Your full name", :maxlength => "55", :autofocus => "autofocus" %>
<%= f.label :email %>
<%= f.email_field :email, :class => "target", :placeholder => "example#gmail.com", :maxlength => "55" %>
<%= f.label :password %>
<%= f.password_field :password, :class => "target", :placeholder => "Enter a password", :maxlength => "55" %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, :class => "target", :placeholder => "Enter your password again", :maxlength => "55" %>
<%= f.fields_for :preference do |builder| %>
<%= builder.hidden_field :layout, value: params[:layout] %>
<%= builder.hidden_field :background_fill, value: params[:background_fill] %>
<%= builder.hidden_field :background_position, value: params[:background_position] %>
<% end %>
<%= f.submit "Create an Account", :class => "button cta" %>
<% end %>
And my parameters
{"utf8"=>"✓",
"authenticity_token"=>"[redacted]=",
"user"=>{"full_name"=>"test",
"email"=>"test#example.com",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]",
"preference"=>{"layout"=>"layout-3",
"background_fill"=>"restaurant-2",
"background_position"=>"position-center"}},
"commit"=>"Create an Account"}
Edit:
The error I get is Preference(#70124732528700) expected, got ActiveSupport::HashWithIndifferentAccess(#70124687315200). My understanding is that #user.build_preference and accepts_nested_attributes_for :preference would just work on its own.
Do I need to create a def preferences_attributes= as per?
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
Update
Okay so I think I'm getting a bit closer. Poking around in the rails console, I figured I need to create Preference.new inside the UserController before I can pass in the hash. Since I'm not sure sure what build_preference does exactly, I'm not having any luck yet.
I've tried adding #user.preference = Preference.new above build preference and changing f.field_for :preference to f.field_for #user.preference but I'm still getting the same error.
Update 2
For anyone else that's stuck on this problem, the answer is to change f.field_for :preference to f.field_for :preference_attributes. See comment below by zetetic.
it is:
attr_accessible :preference_attributes
and in your form:
<%= f.fields_for :preference_attributes do |builder| %>
...
Give a shot.
In your User model, try to add :preference_attributes to your attr_accessible line.
class User < ActiveRecord::Base
attr_accessible :email, :full_name, :password, :password_confirmation, :preference_attributes
.. # rest of your code goes here
end
I know this question has been asked a bunch of times. I already have nested fields_for in my app many times w/o issue so I'm confused as to why its not working this time. I apologize for bringing this topic up again.
I have a user model. A user can have many accounts. To prevent a user from existing w/o at least one account I have a semantic_fields_for nested in the new user form with just one input for setting account role_id.
class User
attr_accessible :accounts_attributes
has_many :accounts, :dependent => :destroy
accepts_nested_attributes_for :accounts
class Account
attr_accessible :role_id, :user_id, :status
belongs_to :role
belongs_to :user
users/new
<%= f.semantic_fields_for :accounts do |account| %>
<%= account.input :role, :as => :select, :collection => #roles, :label => "Account" %>
<% end %>
So, to recap: I have the association set up between users and accounts, users model includes accepts_nested_attributes_for, users model includes attr_accessible :accounts_attributes, semantic_fields_for is set up correctly. The error I get is:
Can't mass-assign protected attributes: accounts
The stack trace from the submitted form includes all the correct variables. Account role_id is being set correctly by the nested attribute. The record is simply being rejected for mass-assignment error but it sure seems my attributes are all properly protected.
Using Rails 3.2.3 and Formtastic 2.2.
EDITED
class UsersController
def new
#user = User.new
#user.accounts.build
end
users/new
<%= semantic_form_for :user, :url => users_path do |f| -%>
<%= f.inputs do %>
<%= f.input :name %>
<%= f.input :username %>
<%= f.input :email %>
<%= f.input :password, :as => :password %>
<%= f.input :password_confirmation, :label => "Confirm Password", :as => :password %>
<%= f.input :school_id, :as => :hidden, :input_html => {:value => #school.id} %>
<%= f.semantic_fields_for :accounts do |account| %>
<%= account.input :role_id, :as => :select, :collection => #roles %>
<% end %>
<%- end -%> <%# END f.inputs do %>
<%= submit_tag 'Create User', :class => "button" %>
<%- end -%> <%# END form %>
GOT IT!! I removed :url => and changed :user to #user in the semantic_form_for block... I guess the way I had it was causing the params[:account] to set off mass assignment
Try adding this to your to your User class
attr_accessible :accounts_attributes
Here's my user model:
class User < ActiveRecord::Base
has_one :teacher, :dependent => :destroy
accepts_nested_attributes_for :teacher, :allow_destroy => true
attr_accessible :email, :password, :password_confirmation, :remember_me, :teacher_attributes
end
Here's my teacher model:
class Teacher < ActiveRecord::Base
belongs_to :user
attr_accessible :user_id, :first_name, :last_name
validates_presence_of :user_id, :first_name, :last_name
end
Here's my form:
<%= form_for(#user, :url => registration_path(:user)) do |user| %>
<%= user.text_field :email %>
<%= user.text_field :password %>
<%= user.text_field :password_confirmation %>
<%= user.fields_for resource.build_teacher do |t| %>
<%= t.text_field :first_name %>
<%= t.text_field :last_name %>
<%= t.text_field :phone %>
<% end %>
<%= user.submit 'Confirm' %>
<% end %>
Except that this thing won't "accept nested attributes"
My development log says:
WARNING: Can't mass-assign protected attributes: teacher
I don't know if it's related, but the form isn't generating fields inside a teacher_attributes array or anything - it's inside teacher. I'm guessing that's where my problem is, but I don't how to make it put the fields inside it. Please help.
Thanks!
Try these things:
At top of view:
<% #user.build_teacher if #user.teacher.nil? %>
For the fields for:
<%= user.fields_for :teacher do |t| %>
Also, personally, I like naming the block parameters in forms (the part |user| and |t|) as |form| (because when you're having a long day, and you see user down in the view and not form, it can confuse you!)