Nested form undefined method `model_name' - ruby-on-rails

I have nested forms dealing with 3 models. Job, Employer, User
The form on the jobs controller needs to create a job, employer and user.
The Job and Employer forms are working correctly, however when I add the User nested form I get the error "undefined method `model_name' for NilClass:Class"
I'm completely confused as to why.
Here is my code:
Job Model
attr_accessible :category, :employer_id, :employer_attributes, :user_attributes
belongs_to :employer
accepts_nested_attributes_for :employer, :user
has_many :applications
has_many :users, :through => :applications
Employer model
attr_accessible :companyname, :email, :logo, :password, :url
has_many :jobs
belongs_to :user
User Model
attr_accessible :admin, :cv, :name, :password, :website, :password_confirmation
has_many :applications
has_many :jobs, :through => :applications
has_one :employer
_form.html.erb
<%= form_for(#job) do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.fields_for :employer do |builder| %>
<%= builder.label :companyname, "Company Name" %>
<%= builder.text_field :companyname %>
<% end %>
<%= f.fields_for :user do |builder| %>
<%= builder.label :email, "Email" %>
<%= builder.text_field :email %>
<%= builder.label :password, "Password" %>
<%= builder.text_field :password %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Job Controller
def new
#job = Job.new
#job.employer = #job.build_employer
#job.user = #job.build_user

To doesn't look like your Job model has a user method. You may need to add
belongs_to :user

Related

How to to pass a parameter to update action?

In my app users has many companies, and companies has many users, companies has many divisions and users have different division in different company for example User with id 1 belongs to Company 1 and Division 2 and to Company 2 Division 3
User.rb
class User < ActiveRecord::Base
has_many :companies, through: :users_companies
has_many :users_companies
has_many :divisions, through: :users_divisions
has_many :users_divisions
has_many :users_roles, dependent: :destroy
has_many :roles, through: :users_roles
end
Company.rb
class Company < ActiveRecord::Base
#before_create :create_division
has_many :users_companies
has_many :users, through: :users_companies
has_many :divisions, dependent: :destroy
has_many :positions
end
Division.rb
class Division < ActiveRecord::Base
has_ancestry
belongs_to :company
has_many :users, through: :users_divisions
has_many :users_divisions
end
UsersCompany.rb
class UsersCompany < ActiveRecord::Base
belongs_to :user
belongs_to :company
end
UsersDivision.rb
class UsersDivision < ActiveRecord::Base
belongs_to :user
belongs_to :division
belongs_to :company
end
UsersDivision table have structure
id|user_id|division_id|company_id
when create all be fine
UsersDivision.create!(user: #user, division_id: params[:user][:division_ids], company_id: #company.id)
but when I try to update #user in table UsersDivision column company_id will be nill.
def update
#company = Company.find(params[:company_id])
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to :back
end
end
How to pass params :company_id to update action?
<div class="edit-registration-container">
<%= #user.full_name %>
<%= form_for([#company, #user]) do |f| %>
<%= f.label :last_name, "Фамилия" %><br />
<%= f.text_field :last_name, type: "text" %>
<%= f.label :first_name, "Имя" %><br />
<%= f.text_field :first_name, type: "text" %>
<%= f.label :middle_name, "Отчество" %><br />
<%= f.text_field :middle_name, type: "text" %>
<%= f.label :division_ids, "Подразделение" %><br />
<%= f.select :division_ids, #divisions_select %><br />
<%= f.hidden_field :company_id, value: #company.id %>
<%= f.fields_for :positions, #position do |ff| %>
<%= ff.label :name, "Должность" %>
<%= ff.text_field :name, type: "text" %>
<%= ff.hidden_field :company_id, value: #company.id %>
<% end %>
<%= hidden_field_tag "user[role_ids][]", nil %>
<% Role.all.each do |role| %>
<%= check_box_tag "user[role_ids][]", role.id, #user.role_ids.include?(role.id), id: dom_id(role) %>
<%= label_tag dom_id(role), role.name %><br>
<% end %>
<%= f.submit "Сохранить", class: "login loginmodal-submit", type: "submit" %>
<% end %>
</div>
You need to permit that parameter to be accessible, so add it in your
user controller params permit:
params.require(:user).permit(YOUR PARAMETERS, {:company_id => []})
Then you can call it using:
params["user"]["company_id"]
I think you can simply do this inside your update action:
#company = Company.find(params["user"]["company_id"])
Here is my working example form:
<%= form_for :user, :url => custom_users_path do |f| %>
<%= f.text_field :name %>
<%= f.hidden_field :company_id, :value => Company.find(1).id %> #4
<%= f.submit "Submit" %>
After I submit, inside my custom action my params["user"]["company_id"] would have this value: 4

'Can't mass-assign protected attributes' when implementing Multiple Table Inheritance with nested forms

HI I am trying to implement the MTI in my application. I have a Person Model and 2 models inheriting from it: Client and TeamMember. When creating a Team Member I want to save to to database vallues for both person (first and last name, email etc) and team member(experience level, type of team, if lead or not). I am using the nested attributes form so in my team member form I am nesting the person fields. Unfortunatellly I am getting "Can't mass-assign protected attributes: person" error when trying to save. Can anyone tell me how this can be solved? Thanks!
Models:
UPDATED TeamMember class but still the same error
also tried people_attributes and persons_attributes and none of these worked
class TeamMember < ActiveRecord::Base
has_many :project_team_members
has_many :projects, through: :project_team_members
has_one :person, as: :profile, dependent: :destroy
accepts_nested_attributes_for :person
attr_accessible :person_attributes, :experience_level, :lead, :qualification, :team
end
class Person < ActiveRecord::Base
belongs_to :company
belongs_to :profile, polymorphic: true
attr_accessible :email, :first_name, :last_name, :phone_number, :profile_id, :profile_type
end
Controller as follows:
class TeamMembersController < ApplicationController
def create
person = Person.create! { |p| p.profile = TeamMember.create!(params[:team_member]) }
redirect_to root_url
end
and the view:
<%= form_for(#team_member) do |f| %>
<%= f.fields_for :person do |ff| %>
<div>
<%= ff.label :first_name %>
<%= ff.text_field :first_name %>
</div>
<div>
<%= ff.label :last_name %>
<%= ff.text_field :last_name %>
</div>
<div>
<%= ff.label :phone_number %>
<%= ff.text_field :phone_number %>
</div>
<div>
<%= ff.label :email %>
<%= ff.text_field :email %>
</div>
<div>
<%= ff.label :company_id %>
<%= ff.text_field :company_id %>
</div>
<% end %>
<div class="field">
<%= f.label :team %><br />
<%= f.text_field :team %>
</div>
<div class="field">
<%= f.label :experience_level %><br />
<%= f.text_field :experience_level %>
</div>
<div class="field">
<%= f.label :qualification %><br />
<%= f.text_field :qualification %>
</div>
<div class="field">
<%= f.label :lead %><br />
<%= f.check_box :lead %>
</div>
<div class="actions">
<%= f.submit %>
</div>
UPDATED TeamMembersController (Solution thanks to the courtesy of Tiago)
def new
#team_member = TeamMember.new
#team_member.build_person
respond_to do |format|
format.html # new.html.erb
format.json { render json: #team_member }
end
end
def create
#team_member = TeamMember.create!(params[:team_member])
redirect_to root_url
end
To mass assign attributes in a nested form, you'll need to specify:
class TeamMember < ActiveRecord::Base
has_many :project_team_members
has_many :projects, through: :project_team_members
has_one :person, as: :profile, dependent: :destroy
:experience_level, :lead, :qualification, :team #what is this line doing??
accepts_nested_attributes_for :person
attr_accessible :person_attributes
end
EDIT:
In the action called before the form you need to build person. Like:
#team_member = TeamMember.new
#team_member.build_person
Then you'll have one person (non-persisted) associated with #team_member.

Nested form not rendering Rails 3.2

The nested form in the view just won't render, unless I remove the f attribute, in which case the submit button will not work. I have two models, job and employer. I've been following the railscast here
job.rb
attr_accessible :title, :location, :employers_attributes,
belongs_to :employers
accepts_nested_attributes_for :employers
employer.rb
attr_accessible :companyname, :url
has_many :jobs
jobs_controller.rb
def new
#job = Job.new
#employer = Employer.new
end
_form.html
<%= form_for(#job) do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :location %>
<%= f.text_field :location %>
<%= f.fields_for :employers do |builder| %>
<%= builder.label :companyname, "Company Name" %>
<%= builder.text_field :companyname %>
<%= builder.label :url, "Web Address" %>
<%= builder.text_field :url %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Any input would be brilliant - thanks
This happens because your job has no employers.
Change your code to this:
def new
#job = Job.new
#job.employer = #job.build_employer
end
In your job.rb change:
attr_accessible :title, :location, :employer_attributes,
belongs_to :employer
accepts_nested_attributes_for :employer
This line:
belongs_to :employers
Should be singulars:
belongs_to :employer
With this association you not need nested form you can use select for pick employer for each job.
But if you need many employers for each job and each job can have many employers see this screencast

Rails fields_for won't see my field inside

I am trying to create two object at the same time. The best approach I have is to used fields_for. and the relationship is has_many.
model/location.rb
attr_accessible :address, :customer_id, :event_id, :latitude, :longitude
belongs_to :customer
belongs_to :event
model/event.rb
attr_accessible :locations_attributes
has_many :locations, :dependent => :destroy
accepts_nested_attributes_for :locations
The form is has follow:
<%= form_for(#event) do |f| %>
...
<%= f.fields_for :locations do |e| %>
<%= e.text_field :longitude %>
<%= e.text_field :latitude %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My fields won't show up, I have followed the documentation has_many from this section http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
and notice if in my f.fields_for :locations change it to singular than the fields will show up but i won't be able to create it because i am not allow to modify the locations_attributes.
UPDATE:
If i singular it. I change this to my event model
attr_accessible :description, :title, :location_attributes
The error is like this
app/controllers/events_controller.rb:60:in `new'
app/controllers/events_controller.rb:60:in `create'
My controller is like this
line 60: #event = Event.new(params[:event])
You should be doing this in your form: (location not locations)
<%= f.fields_for :location do |e| %>
<%= e.text_field :longitude %>
<%= e.text_field :latitude %>
<% end %>
and in your model event.rb
attr_accessible :description, :title, :locations_attributes (locations not location)

How do I make nested_attributes work in Rails3?

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!)

Resources