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
Related
Here personaldetails belongs_to user and the relation given is has_many which is wrong.I want to convert the has_many relation to has_one relation i.e. User has_one personaldetails. When I change the relation directly I am getting an error "uninitialized constant User::Personaldetails. Please guide me how to convert the relation .
Personaldetail.rb
class Personaldetail < ApplicationRecord
belongs_to :user
end
User.rb
class User < ApplicationRecord
has_many :personaldetails, dependent: :destroy
accepts_nested_attributes_for :personaldetails, reject_if: :all_blank, allow_destroy: true
end
routes.rb
resources :users, except: [:new] do
resources :personaldetails
end
user_steps_controller.rb
class UserStepsController < ApplicationController
include Wicked::Wizard
steps : :personaldetails
def show
#user = current_user
#personaldetails = #user.personaldetails.build
render_wizard
end
def update
#user = current_user
#user.update!(user_params)
render_wizard #user
end
private
def user_params
params.require(:user).permit(:name, :password, :password_confirmation, :user_id,
personaldetails_attributes: [:id,:first_name, :last_name, :gmail, :mobile_no, :city, :state, :pin_code, :_destroy])
end
end
personaldetails.html.erb
<%= form_with(model: #user, url: wizard_path, local: true) do |form| %>
<%= form.fields_for :personaldetail,Personaldetail.new do |info| %>
<%= render 'personaldetails_field', form: info %>
<% end %>
<%= form.submit %>
<% end %>
_personaldetails_field.html.erb
<div class="field">
<%= form.label :First_name %><br />
<%= form.text_field :first_name %>
</div>
<div class="field">
<%= form.label :Last_name %><br />
<%= form.text_field :last_name %>
</div>
<div class="field">
<%= form.label :email %><br />
<%= form.text_field :gmail %>
</div>
<div class="field">
<%= form.label :Mobile_number %><br />
<%= form.text_field :mobile_no %>
</div>
<div class="field">
<%= form.label :City %><br />
<%= form.text_field :city %>
</div>
<div class="field">
<%= form.label :State %><br />
<%= form.text_field :state %>
</div>
<div class="field">
<%= form.label :Pincode %><br />
<%= form.text_field :pin_code %>
</div>
So the solution is:
Personaldetail.rb
class Personaldetail < ApplicationRecord
belongs_to :user
end
User.rb
class User < ApplicationRecord
has_one :personaldetails, dependent: :destroy
accepts_nested_attributes_for :personaldetails, reject_if: :all_blank, allow_destroy: true
end
routes.rb
resources :users, except: [:new] do
resources :personaldetail
end
user_steps_controller.rb
class UserStepsController < ApplicationController
include Wicked::Wizard
steps : :personaldetails
def show
#user = current_user
render_wizard
end
def update
#user = current_user
#user.update!(user_params)
render_wizard #user
end
private
def user_params
params.require(:user).permit(:name, :password, :password_confirmation, :user_id,
personaldetails_attributes: [:id,:first_name, :last_name, :gmail, :mobile_no, :city, :state, :pin_code, :_destroy])
end
end
personaldetail.html.erb
<%= form_with(model: #user, url: wizard_path, local: true) do |form| %>
<%= form.fields_for :personaldetail,#user.personaldetail || #user.build_personaldetail do |info| %>
<%= render 'personaldetail_field', form: info %>
<% end %>
<%= form.submit %>
<% end %>
_personaldetail_field.html.erb
<div class="field">
<%= form.label :First_name %><br />
<%= form.text_field :first_name %>
</div>
<div class="field">
<%= form.label :Last_name %><br />
<%= form.text_field :last_name %>
</div>
<div class="field">
<%= form.label :email %><br />
<%= form.text_field :gmail %>
</div>
<div class="field">
<%= form.label :Mobile_number %><br />
<%= form.text_field :mobile_no %>
</div>
<div class="field">
<%= form.label :City %><br />
<%= form.text_field :city %>
</div>
<div class="field">
<%= form.label :State %><br />
<%= form.text_field :state %>
</div>
<div class="field">
<%= form.label :Pincode %><br />
<%= form.text_field :pin_code %>
</div>
try with: has_one :personaldetail, dependent: :destroy
Rails are guessing class name from name AND type of association, so with has_many they will try to singularize association name (personaldetails => Personaldetail) but with has_one they will try to reach it as is (personaldetails => Personaldetails)
As in the comment by spickermann, has_many relationship wants plural form and has_one the singular form.
That is to say, you should already be able to infer the relationship from:
#user.personaldetails # user has many personal details
#user.personaldetail # user has one personal detail
Just a consideration: many weird cases arise when objects/models are not properly named. As a rule of thumb, you should use the most fitting and precise English noun for the object you need to name. That will help you hugely in cases like this. In normal English language, it is somehow strange to say "a user has a personal detail" but you would say of course "has personal details". Particularly when it comes to ActiveRecord associations, Rails syntax should be the nearest as possible to English language, to avoid later misunderstandings. I guess this confusion would not have arisen if instead of "PersonalDetail", the model was called "Account" or "Profile", for instance.
Few suggestions/comments
Keep model name as CamelCase like PersonalDetail rather than Personaldetail and association name has_one :personal_detail
Using has_one relation you can create the object using user.build_personal_detail.save
When you run the 2nd step again it will create another record in personal_details table and in that transaction it will return the new record. But, after that when you try to query it will return the 1st created personal_details record rather than new one. That's because ActiveRecord by default sorts by id and limit 1 for has_one relation
I'm trying to implement accepts_nested_attributes_for on my app. When I add accepts_nested_attributes_for :account to the user.rb the nested fields disappear. When I delete accepts_nested_attributes_for :account the fields appear but no data is being saved when I click on submit.
Any ideas why this is happening?
I have two models with appropriate associations added:
user.rb
has_one :account
has_many :items
accepts_nested_attributes_for :account
account.rb
belongs_to :user
app/controllers/users/registrations.controller.rb
before_action :configure_permitted_parameters, if: :devise_controller?
def new
build_resource({})
resource.build_account
respond_with self.resource
session[:registration_params] = request.query_parameters
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u|
u.permit(:email, :password, :password_confirmation, :remember_me,
:account_attributes => [:first_name, :last_name, :buisness_name,
:buisness_description, :web_site, :phone_number,
:street, :city, :state, :zip_code, :country])
}
end
new.html.erb
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<%= f.fields_for :account do |form| %>
<div class="field">
<%= form.label :first_name %>
<%= form.text_field :first_name, id: :account_first_name %>
</div>
<div class="field">
<%= form.label :last_name %>
<%= form.text_field :last_name, id: :account_last_name %>
</div>
<div class="field">
<%= form.label :buisness_name %>
<%= form.text_field :buisness_name, id: :account_buisness_name %>
</div>
<div class="field">
<%= form.label :buisness_description %>
<%= form.text_field :buisness_description, id: :account_buisness_description %>
</div>
<div class="field">
<%= form.label :web_site %>
<%= form.text_field :web_site, id: :account_web_site %>
</div>
<div class="field">
<%= form.label :phone_number %>
<%= form.text_field :phone_number, id: :account_phone_number %>
</div>
<div class="field">
<%= form.label :street %>
<%= form.text_field :street, id: :account_street %>
</div>
<div class="field">
<%= form.label :city %>
<%= form.text_field :city, id: :account_city %>
</div>
<div class="field">
<%= form.label :state %>
<%= form.text_field :state, id: :account_state %>
</div>
<div class="field">
<%= form.label :zip_code %>
<%= form.text_field :zip_code, id: :account_zip_code %>
</div>
<div class="field">
<%= form.label :country %>
<%= form.text_field :country, id: :account_country %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
I had to add the controller to routes.rb devise_for :users
devise_for :users, controllers: {registrations: 'users/registrations'}
You can use cocoon gem for nested attributes. It will make handling nested attributes lot more easier
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.
I have a BikeShops model:
class BikeShop < ActiveRecord::Base
has_one :user, :as => :profile, :dependent => :destroy
accepts_nested_attributes_for :user
end
And a Users model:
class User < ActiveRecord::Base
belongs_to :profile, :polymorphic => true
end
I am trying to create a nested form in the bike_shops/new view. Here is the code I have: in there:
<%= form_for(#bike_shop) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, 'Shop Name' %>
<%= f.text_field :name %>
<%= f.label :street_address, 'Street Address' %>
<%= f.text_field :street_address %>
<%= f.label :city, 'City' %>
<%= f.text_field :city %>
<%= f.label :state, 'State' %>
<%= f.text_field :state %>
<%= f.label :zip_code, 'Zip Code' %>
<%= f.text_field :zip_code %>
<%= f.label :phone_number, 'Phone Number' %>
<%= f.text_field :phone_number %>
<%= f.label :website, 'Website' %>
<%= f.text_field :website %>
<% f.fields_for(:user) do |builder| %>
<%= builder.label :first_name, 'First Name:' %>
<%= builder.text_field :first_name %>
<%= builder.label :last_name, 'Last Name:' %>
<%= builder.text_field :last_name %>
<%= builder.label :email, 'Email:' %>
<%= builder.text_field :email %>
<%= builder.label :password, 'Password:' %>
<%= builder.password_field :password %>
<%= builder.label :password_confirmation, 'Password Confirmation:' %>
<%= builder.password_field :password_confirmation %>
<% end %>
<%= f.submit "Signup My Bike Shop", class: "btn btn-large btn-primary" %>
<% end %>
The fields for #bike_shop appear but the nested fields for the has_one #user do not appear. Here is the code in the BikeShops controller:
class BikeShopsController < ApplicationController
def new
#bike_shop = BikeShop.new
#user = #bike_shop.build_user
end
I was following this railscast but can't get pass getting the fields for the nested form to show. Any help is appreciated.
You need to use the <%= erb tag in order to render it instead of just <%
<%= f.fields_for(:user) do |builder| %>
I want my users to be able to select from predefined values of categories. I took a look at other Stackoverflow questions but didn't get them fully. Here is my code right now....
I have my Categories model and Users create prices (which is another name for Items).
class Category < ActiveRecord::Base
has_many :prices
def name
"#{category}"
end
end
My prices belong to categories. note: The prices table has a category_id.
class Price < ActiveRecord::Base
attr_accessible :name, :date, :price
belongs_to :user
belongs_to :category
end
Here is how the form and view look as of now:
Form
<%= form_for(#price) do |f| %>
<div class="field">
<%= f.label :date %><br />
<%= f.date_select :date %>
</div>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :price %><br />
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :category %><br />
<%= f.collection_select :category_id, Category.all, :id, :name, :prompt => true %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
View
<p><b>User:</b><%= #price.user_id %></p>
<p><b>Date:</b><%= #price.date %> </p>
<p><b>Name:</b><%= #price.price_name %></p>
<p><b>Price:</b><%= number_to_currency(#price.price) %></p>
<p><b>Category:</b><%= #price.category.name %></p>
How do i create the categories i want in the drop down menu?
Thank you I'm a very appreciative!
You probably want the collection_select form helper method: http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select
It will look something like this:
<div class="category">
<%= f.label :category %><br />
<%= f.collection_select :category, Category.all, :id, :name %>
</div>
Then in the view:
<p><b>Category:</b><%= #price.category.name %></p>
This assumes that your categories table has a name field which stores the category names.
you can create your data in db/seeds.rb
rake db:seed to load them (Load the seed data from db/seeds.rb)
http://railscasts.com/episodes/179-seed-data for more details