I have looked at all the posts about this fairly common problem on stackoverflow and elsewhere but I have not yet been able to find an answer. Essentially my nested form is not building, and is therefore not visible when I show the page.
Here is the relevant part of my user controller, users_controller.rb:
def new
#user = User.new
#user.build_user_account
end
Here is the relevant section from my user.rb file:
class User < ActiveRecord::Base
has_one :user_account, :class_name => "UserAccount"
accepts_nested_attributes_for :user_account
And my user_account.rb file:
class UserAccount < ActiveRecord::Base
belongs_to :user
end
Here is my _form.html.erb file:
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br>
<%= f.text_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br>
<%= f.text_field :password_confirmation %>
</div>
<% f.fields_for :user_account, #user.user_account do |user_account| %>
<div class="field">
<%= user_account.label :email %>
<%= user_account.text_field :email %>
</div>
<div class="field">
<%= user_account.label :password %>
<%= user_account.text_field :password %>
</div>
<div class="field">
<%= user_account.label :password_confirmation %>
<%= user_account.text_field :password_confirmation %>
</div>
<% end %>
the first three show up as expected, but the three form fields for user_account do not show up. I've tried everything that I could find online, but I still haven't been able to work out what the problem is - help would be appreciated!
I think you have just missed the = sign in the f.fields_for line. Try like this:
<%= f.fields_for :user_account, #user.user_account do |user_account| %>
The #user.user_account is not necessary either but does not harm.
Related
I have a problem in my form, i want to create an entry in my "members" table, each member are connected to a "year" but I keep getting mismatches on the selection of the year.
This is my form:
<div class="field">
<%= f.label :name %><br>
<%= f.text_area :name %>
</div>
<div class="field">
<%= f.label :nickname %><br>
<%= f.text_area :nickname %>
</div>
<div class="field">
<%= f.label :year %>
<%= f.select :year, options_for_select(#years.all.map{|y| [y.year,y.id]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
And here are the models:
class Member < ApplicationRecord
belongs_to :year
mount_uploader :image, ImageUploader
end
class Year < ApplicationRecord
has_many :members, dependent: :destroy
end
When I try to submit I get the following error:
Year(#70050157849460) expected, got "1" which is an instance of String(#9412380)
Where did I go wrong?
EDIT:
Here is the code for the controller
class MembersController < ApplicationController
def home
#members = Member.all
end
def new
#member = Member.new
#years = Year.all
end
def create
#member = Member.new(member_params)
if #member.save
flash[:success] = "Member Created"
redirect_to root_path
else
render 'form'
end
end
private
def member_params
params.require(:member).permit(:name,:nick,:position,:image,:year)
end
end
<div class="field">
<%= f.label :name %><br>
<%= f.text_area :name %>
</div>
<div class="field">
<%= f.label :nickname %><br>
<%= f.text_area :nickname %>
</div>
<div class="field">
<%= f.label :year %>
<%= f.select :year_id, options_for_select(#years.all.map{|y| [y.year,y.id]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
or
<div class="field">
<%= f.label :name %><br>
<%= f.text_area :name %>
</div>
<div class="field">
<%= f.label :nickname %><br>
<%= f.text_area :nickname %>
</div>
<div class="field">
<%= f.label :year %>
<%= f.select :year, options_for_select(#years.all.map{|y| [y.year,y]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
This second I did not check but first will work you need to say year_id because when you did map on collection you set id as parameter that is being passed
but on form select you basically told form to expect active record object.
I want the user to be able to register in two steps as I have many fields. Ideally first step would be to accept email and password. As user enter it, they can proceed to fill the next step.
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :first_name %>
<%= f.text_field :first_name, autofocus: true %>
</div>
<div class="field">
<%= f.label :last_name %>
<%= f.text_field :last_name %></br>
</div>
<div class="field">
<%= f.label :city %>
<%= f.text_field :city %>
</div>
<div class="field">
<%= f.label :address %>
<%= f.text_area :address %>
</div>
<div class="field">
<%= f.label :gender %>
<span class="option">Male</span><%= f.radio_button :gender, "m" %>
<span class="option">Female</span><%= f.radio_button :gender, "f" %></br>
</div>
<div class="field">
<%= f.label :mobile_no %></br>
<%= f.telephone_field :mobile_no %>
</div>
<div class="field">
<%= f.label :website %>
<%= f.url_field :website %>
</div>
<div class="field">
<%= f.label :email %>
<%= f.email_field :email %>
</div>
<div class="field">
<%= f.label :password %>
<% if #validatable %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :skills %>
<%= f.text_field :skills %>
</div>
<div class="field">
<%= f.label :passion %>
<%= f.text_field :passion %>
</div>
<div class="field">
<%= f.label :description %>
<%= f.text_area :description %>
</div>
<% end %>
I tried the approach where user enters email and password and after that they are redirected to edit page where they can update other fields.
class RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(resource)
redirect_to edit_user_path(resource)
end
end
routes.rb
devise_for :users, :pro, :amateur, controllers: { registrations: "registrations" }
However, the redirect doesn't seem to work. I also tried after_inactive_sign_up_path_for as I am using confirmable, still not working.
I can't seem to figure out why this could be also I would like to know if there are any other approach without using any gem?
You could use javascript if you're just interested in user interface. Or if it's important that you're saving all the info as you're going, you can have the form split into partials and override the devise registration controller to render those separate partials.
You will also need to add steps that link with the partials in your user model. I think if you used a gem, this would probably be main part that it will do for you.
this is a great railscast on how to have a multistep form without any gems. the only difference is that you'll need to override the create method in devise
I have two very similar models Pretreatment and Diagnosis, that belong to the model Patient:
class Pretreatment < ActiveRecord::Base
belongs_to :patient
attr_accessible :content
end
class Diagnosis < ActiveRecord::Base
belongs_to :patient
attr_accessible :content
end
class Patient < ActiveRecord::Base
attr_accessible :age, :name, :city, :street, :number
has_many :anamneses
has_many :befunds
end
On the Patient show page I'm displaying two forms, one for the Preatreatment and another for the Diagnosis:
<%= form_for([#patient, #patient.preatreatments.build]) do |f| %>
<div class="field">
<%= f.label :conten %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= form_for([#patient, #patient.diagnosiss.build]) do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My question is how can I bring the two forms together, so that the user only has to press once the submit button? Im not sure but I think nested attributes is not the right thing to handle it, maybe thefields_for` tag?
Update I tried to use fields_for tag:
<%= form_for([#patient, #patient.pretreatment.build]) do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<%= fields_for([#patient, #patient.diagnosiss.build]) do |u| %>
<div class="field">
<%= u.label :content %><br />
<%= u.text_field :content %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
But I get the error:
undefined method `model_name' for Array:Class in <%= fields_for([#patient,#patient.befunds.build]) do |u| %>
Use fields_for for the associated models.
There should be no square brackets arround the parameters of fields_for
In your code example, I cannot find the relation between Patient and Diagnosis, and the plural of diagnosis is diagnoses, you can specify this in config/initializers/inflections.rb:
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'diagnosis','diagnoses'
end
So your Patient model should contain
class Patient < ActiveRecord::Base
attr_accessible :age, :name, :city, :street, :number
has_many :diagnoses
end
And you can write in your form:
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<%= fields_for(#patient, #patient.diagnoses.build) do |u| %>
<div class="field">
<%= u.label :content %><br />
<%= u.text_field :content %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
You can achieve that using nested attributes :
patient.rb
class Patient < ActiveRecord::Base
attr_accessible :age, :name, :pretreatments_attributes, :diagnosiss_attributes
has_many :pretreatments
has_many :diagnosiss
accepts_nested_attributes_for :pretreatments
accepts_nested_attributes_for :diagnosiss
end
patients_controller.rb
def show
#patient = Patient.find(params[:id])
#patient.pretreatments.build
#patient.diagnosiss.build
respond_to do |format|
format.html # show.html.erb
format.json { render json: #patient }
end
end
patients/show.html.erb:
<%= form_for #patient do |f|%>
<h3>Pretreatments:</h3>
<%= f.fields_for :pretreatments do |field| %>
<%= field.label "Content" %></div>
<%= field.text_field :content %>
<% end %>
<h3>Diagnosis:</h3>
<%= f.fields_for :diagnosiss do |field| %>
<%= field.label "Content" %></div>
<%= field.text_field :content %>
<% end %>
<%=f.submit %>
<% end %>
And that all
There are a few ways of doing this:
The way the fields_for works is you have a form_for for the parent model and within it you can place fields_for the models which belong to the parent. A good example is given in the Rails Docs
A simple and more extensible option over time but not very "semantic" one would be to use JavaScript/JQuery. You could trigger $("form #new_pretreatments").submit(); and the same for the Diagnosis once a button is clicked.
Maybe instead you could have just one model to store them both. For example a model called Disease. Each time a patient gets a disease a new one is created and it has columns for each the Diagnosis and Pretreatment. It's probably the best option instead of adding another model for each bit of info a patient can have.
You can use fields_for for the second model, which works like form_for but doesn't generate the form tags. See the docs.
There are some gems available for nested forms. one of them is awesome_nested_fields. I haven't used this earlier but that shows good code in documentation. Another one is simple_form.
Hope that helps!!!
I use Ruby v 3. I want to display data from 2 tables into one form.
My models:
class Address < ActiveRecord::Base
attr_accessible :city, :number, :street
validates :city, :presence => true
validates :number, :presence => true
validates :street, :presence => true
has_many :users
end
class User < ActiveRecord::Base
belongs_to :address
attr_accessible :name, :phone, :surname, :address_attributes
accepts_nested_attributes_for :address
end
My form looks alike:
<%= form_for(#user) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :surname %><br />
<%= f.text_field :surname %>
</div>
<div class="field">
<%= f.label :phone %><br />
<%= f.text_field :phone %>
</div>
<%= f.fields_for :address_attributes do |p| %>
<div class="field">
<%= p.label :city %><br />
<%= p.text_field :city %>
</div>
<div class="field">
<%= p.label :street %><br />
<%= p.text_field :street %>
</div>
<div class="field">
<%= p.label :number %><br />
<%= p.text_field :number %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
As you can see I use fields_for method. And my controller is here:
def edit
#user = User.find(params[:id])
#user.address_attributes = #user.address
end
It does not working and I totally don't know why. When I click edit on address list i've got an error:
undefined method `with_indifferent_access'
Anyone can help me figure it out?
Check out Episodes 196 and 197 on RailsCasts:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2
There is a revised episode for 196, for which you will need to subscribe to RailsCasts.
I would highly recommend subscribing to learning sites like RailsCasts and CodeSchool, to lear RoR faster and in the right way.
Try to do:
def edit
#user = User.find(parmas[:id])
end
and on your view:
<%= f.fields_for :address do |p| %>
and see if it works, you don't have to add the attributes
I am a bit unsure on how to store the data from a collection_tag.
Here the model I am working on
Customer GenderManager Genders
Id Id Id
First Customer_id Description
Last Gender_id
Email Created_at
Password
Here the relationship
Customer::class
has_many :gender_managers
accepts_nested_attributes_for :gender_managers, allow_destroy: :true
Gender::class
has_many :gender_managers
GenderManagers:class
belongs_to :customer_id
belongs_to :gender_id
The form I have currently his has follow
<%= form_for #customer do |f| %>
<div class="customer_edit_error_message">
<%= render 'shared/error_messages' %>
</div>
<fieldset>
<div class="customer_edit_name">
<%= f.label :first_name %>
<%= f.text_field :first_name %>
</div>
<div class="customer_edit_middle_name">
<%= f.label :middle_name %>
<%= f.text_field :middle_name %>
</div>
<div class="customer_edit_last_name">
<%= f.label :last_name %>
<%= f.text_field :last_name %>
</div>
<div class="customer_edit_gender">
<%= f.collection_select(:customer, :id, Gender.all, :id, :description) %>
</div>
<div class="customer_edit_button">
<%= f.submit "Save changes", class: "button_accept" %>
</div>
<% end %>
In customerController not sure if I must do something. I know its not right its giving me errors. Its the form that worry me on the select like
Thanks in advance.
I recommend you add an attribute gender to your Customer model. If you want to keep track of changes you can create a GenderHistory model and do something like this in Customer:
class Customer < ActiveRecord::Base
has_many :gender_histories
before_update :track_gender
def track_gender
self.gender_histories.create(:gender => self.gender) if self.gender_changed?
end
end
Your Genders and GenderManager models are not necessary.