I am trying to write an app - simple form for user's details which saves data to three different tables (1.users, 2.companies, 3.adresses).
I have set some assosiations using belongs_to and has_many, and also use nested_attributes and fields_for to build one form. But I can't save data.
I am a newbie, so probably I'm making some stupid mistakes, but I cannot really find them since 3 days. Also tried to look in google and here, among forum posts, but didn't find a code, where the problem was connected with child class. My assosiations between user, company and adress are quite weird. Can anyone help me?
Here is my form:
<%= simple_form_for #user do |f| %>
<h5>Personal Details</h5>
<%= f.input :firstname, label: 'Your First Name:' %>
<%= f.input :lastname, label: 'Your Last Name:' %>
<%= f.input :email, label: 'Your Email:' %>
<%= f.input :dateofbirth, label: 'Your Date of Birth:' %>
<%= f.input :phonenumber, label: 'Your Phone Number' %>
<h5>Adress</h5>
<%= f.fields_for :adresses do |g| %>
<%= g.input :street, label: 'Street:' %>
<%= g.input :city, label: 'City:' %>
<%= g.input :zipcode, label: 'Zip Code:' %>
<%= g.input :country, label: 'Country:' %>
<% end %>
<h5>Company</h5>
<%= f.fields_for :companies do |h| %>
<%= h.input :name, label: 'Name:' %>
<% end %>
<%= f.fields_for :adresses do |i| %>
<%= i.input :comstreet, label: 'Street:' %>
<%= i.input :comcity, label: 'City:' %>
<%= i.input :comzipcode, label: 'Zip Code:' %>
<%= i.input :comcountry, label: 'Country:' %>
<% end %>
<%= f.button :submit %>
<% end %>
user.rb
class User < ApplicationRecord
belongs_to :company, inverse_of: :users
belongs_to :adress, inverse_of: :users
validates_presence_of :firstname, :lastname, :email
validates_length_of :firstname, :maximum => 100
validates_length_of :lastname, :maximum => 100
end
company.rb
class Company < ApplicationRecord
has_many :users, inverse_of: :companies
belongs_to :adress, inverse_of: :companies
accepts_nested_attributes_for :users
end
adress.rb
class Adress < ApplicationRecord
has_many :users, inverse_of: :adresses
has_many :companies, inverse_of: :adresses
accepts_nested_attributes_for :users, :companies
end
users_controller
class UsersController < ApplicationController
def index
end
def new
#user = User.new
#company = Company.new
#adress = Adress.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to root_path
end
end
private
def user_params
params.require(:user).permit(:firstname, :lastname, :email, :dateofbirth,
:phonenumber, company_attributes: [:name],
adress_attributes: [:street,:city, :zipcode, :country, :comstreet,
:comctiy, :comzipcode, :comcountry] )
end
end
In your user.rb file:
class User < ApplicationRecord
belongs_to :company, inverse_of: :users
belongs_to :adress, inverse_of: :users
validates_presence_of :firstname, :lastname, :email
validates_length_of :firstname, :maximum => 100
validates_length_of :lastname, :maximum => 100
# add nested attributes here not in other models
accepts_nested_attributes_for :companies
accepts_nested_attributes_for :addresses
end
Also, in your controller: carefully check the names of parameters passed. address_attributes misspelled
def user_params
params.require(:user).permit(:firstname, :lastname, :email, :dateofbirth,
:phonenumber, company_attributes: [:name],
address_attributes: [:street,:city, :zipcode, :country, :comstreet,
:comctiy, :comzipcode, :comcountry] )
end
In the view, remove multiple form elements for address. You wrote twice.
I have made few changes in the code and able to save the form, please check
Here is my form:
<%= simple_form_for #user do |f| %>
<h5>Personal Details</h5>
<%= f.input :firstname, label: 'Your First Name:' %>
<%= f.input :lastname, label: 'Your Last Name:' %>
<%= f.input :email, label: 'Your Email:' %>
<%= f.input :dateofbirth, label: 'Your Date of Birth:' %>
<%= f.input :phonenumber, label: 'Your Phone Number' %>
<h5>Adress</h5>
<%= f.fields_for :adress_attributes do |g| %>
<%= g.input :street, label: 'Street:' %>
<%= g.input :city, label: 'City:' %>
<%= g.input :zipcode, label: 'Zip Code:' %>
<%= g.input :country, label: 'Country:' %>
<% end %>
<h5>Company</h5>
<%= f.fields_for :company_attributes do |h| %>
<%= h.input :name, label: 'Name:' %>
<%= h.fields_for :adress_attributes do |i| %>
<%= i.input :street, label: 'Street:' %>
<%= i.input :city, label: 'City:' %>
<%= i.input :zipcode, label: 'Zip Code:' %>
<%= i.input :country, label: 'Country:' %>
<% end %>
<% end %>
<%= f.button :submit %>
<% end %>
user.rb
class User < ApplicationRecord
belongs_to :company, inverse_of: :users
belongs_to :adress, inverse_of: :users
validates_presence_of :firstname, :lastname, :email
validates_length_of :firstname, :maximum => 100
validates_length_of :lastname, :maximum => 100
accepts_nested_attributes_for :company
accepts_nested_attributes_for :address
end
company.rb
class Company < ApplicationRecord
has_many :users, inverse_of: :companies
belongs_to :adress, inverse_of: :companies
accepts_nested_attributes_for :users
accepts_nested_attributes_for :adress
end
adress.rb
class Adress < ApplicationRecord
has_many :users, inverse_of: :adresses
has_many :companies, inverse_of: :adresses
accepts_nested_attributes_for :users, :companies
end
users_controller
class UsersController < ApplicationController
def index
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to root_path
end
end
private
def user_params
params.require(:user).permit(:firstname, :lastname, :email, :dateofbirth,
:phonenumber, company_attributes: [:name, adress_attributes: [:street,
:ctiy, :zipcode, :country]],
adress_attributes: [:street,:city, :zipcode, :country] )
end
end
It is working now and able to save user, address and company with company address.
I cannot seem to get nested attributes to save to the database, though I can see the params in terminal. I am using Rails 4.2.
Here are my models:
class Device < ActiveRecord::Base
belongs_to :hub
has_many :accessories, dependent: :destroy
accepts_nested_attributes_for :accessories,
reject_if: proc { |attributes| attributes['material'].blank? },
allow_destroy: true
end
class Accessory < ActiveRecord::Base
belongs_to :device
end
Here is the controller. I have my device model nested under user and hub model.
class DevicesController < ApplicationController
def edit
#user = User.find_by(params[:user_id])
#hub = Hub.find_by_title(params[:hub_id])
#device = Device.find_by(id: params[:id])
end
def update
#user = User.find_by(params[:user_id])
#hub = Hub.find_by_title(params[:hub_id])
#device = Device.find_by(id: params[:id])
if #device.update_attributes(device_params)
flash[:success] = "update successfully"
redirect_to user_hub_device_path(#user, #hub, #device)
else
render 'edit'
end
end
private
def device_params
params.require(:device).permit(:model, :hub_id, :resolution, :materials, :startcost, :take_online, :delivery_time, :unitcost, :color, :accessories, :accessories_attributes => [:id, :name, :cost, :color, :device_id, :_destroy])
end
end
Finally is my form.
<%= form_for([#user, #hub, #device]) do |f| %>
<fieldset>
<div id="material">
<%= f.fields_for :accessories do |a| %>
<%= render 'devices/accessory', a: a %>
<% end %>
</div>
</fieldset>
The partial:
<div class="row">
<%= a.collection_select :name, Material.all, :material, :material %>
<%= a.text_field :cost, id: "right-label" %>
<%= a.text_field :color, id: "right-label" %>
<%= a.check_box :_destroy %>
</div>
You are whitelisting params[:device][:materials] but you are checking attributes['material'].blank? (note the the s on the end). Which causes the nested attributes to be rejected.
I'm confused writing my backend for the barangay profiles. In my form there is a field where ask to input the your barangay then when it save the barangay field will be save at the barangay model. In the brgyprofile it is associated to barangay model where the id of barangay model is FK of brgyprofile model. How can I save the data in barangay model. I already try to twerk it but nothing happens. brgy_name didn't save in the barangay model. I'm confuse how. I'm really new to rails and trying to create an app.
routes.rb
resources :brgyadmins do
resources :brgyprofiles
end
models
class Brgyprofile < ActiveRecord::Base
belongs_to :barangay
belongs_to :brgyadmin
end
class Barangay < ActiveRecord::Base
has_one :brgyprofile
end
_form.html.erb
<%= simple_form_for ([#brgyadmin,#new_profile]) do |f| %>
<%= f.input :firstname, placeholder: 'Firstname' %>
<%= f.input :lastname, placeholder: 'Lastname' %>
<%= f.input :birthdate, :order => [:month, :day, :year] %>
<%= f.input :gender,
:as => :radio_buttons,
:collection => %w[Female Male]
%>
<%= f.input :brgy_name, placeholder: 'Barangay' %>
<%= f.input :brgy_position, placeholder: 'Barangay Position' %>
<%= f.input :contact_number, placeholder: 'Contact Number' %>
<%= f.button :submit, 'Submit' %>
<% end %>
brgyprofile controller
class BrgyprofilesController < ApplicationController
before_action :set_brgyprofile, only: [:new, :create]
def new
#new_profile = #brgyadmin.build_brgyprofile
end
def create
#respond_to do |format|
if #brgyadmin.create_brgyprofile(profile_params) && Barangay.create(brgy_name: params[:brgy_name])
logger.info "Saved!"
else
logger.info "Nothing happens"
end
#end
end
private
def set_brgyprofile
#brgyadmin = Brgyadmin.find(session[:user_id])
end
def profile_params
params.require(:brgyprofile).permit(:firstname, :lastname, :birthdate, :gender, :brgy_position, :contact_number, :barangay_id, :brgy_name)
end
end
I'm trying to update my associated model, but it's not updating to the database and i'm not sure what to try next.
Model
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation,
:remember_me, :username, :login, :first_name,
:last_name, :home_phone, :cell_phone,
:work_phone, :birthday, :home_address,
:work_address, :position, :company, :user_details
has_one :user_details, :dependent => :destroy
accepts_nested_attributes_for :user_details
end
class UserDetails < ActiveRecord::Base
belongs_to :user
attr_accessible :home_phone, :position
end
Controller
# PUT /contacts/1/edit
# actually updates the users data
def update_user
#userProfile = User.find(params[:id])
respond_to do |format|
if #userProfile.update_attributes(params[:user])
format.html {
flash[:success] = "Information updated successfully"
render :edit
}
else
format.html {
flash[:error] = resource.errors.full_messages
render :edit
}
end
end
end
View
<%= form_for(#userProfile, :url => {:controller => "my_devise/contacts", :action => "update_user"}, :html => {:class => "form grid_6"}, :method => :put ) do |f| %>
<%= f.label :username, "Username" %>
<%= f.text_field :username, :required => "required" %>
<%= f.fields_for :user_details do |d| %>
<%= d.label :home_phone, "Home Phone" %>
<%= d.text_field :home_phone %>
<% end %>
<% end %>
<% end %>
Your attr_accessible should accept user_details_attributes, not just user_details.
I have four controllers - users, categories, stories and comments. My problem is with comments. When I submit a comment #comment.save is false and I can't understand where is the problem. My table in DB for Comment has content, user_id, story_id. Here is part of my code:
def new
#comment = Comment.new
#story = Story.find(params[:story_id])
end
def create
#story = Story.find(params[:story_id])
if current_user
#comment = current_user.comments.create(params[:comment])
end
if #comment.save
flash[:success] = "Successfull added comment"
redirect_to story_path(#story)
else
render 'new'
end
end
show.html.erb for StoriesController:
<b><%= #story.title %></b> <br/><br/>
<%= #story.content %> <br/><br/>
<% #story.comments.each do |comment| %>
<b>Comment:</b>
<%= comment.content %>
<% end %>
<%= form_for([#story, #story.comments.build]) do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_area :content %>
</div>
<div class="actions">
<%= f.submit "Add" %>
</div>
<% end %>
comment.rb:
class Comment < ActiveRecord::Base
attr_accessible :content, :story_id, :user_id
belongs_to :story
belongs_to :user
validates :content, :presence => true
validates :story_id, :presence => true
validates :user_id, :presence => true
default_scope :order => 'comments.created_at DESC'
end
story.rb
class Story < ActiveRecord::Base
attr_accessible :title, :content, :category_id
belongs_to :user
belongs_to :category
has_many :comments
validates :title, :presence => true
validates :content, :presence => true
validates :user_id, :presence => true
default_scope :order => 'stories.created_at DESC'
end
UPDATE
When I use save! I have an error message Story cannot be blank.
You need to set the story for the comment your are building since (as you've obviously worked out), the story in question is given by params[:story_id]. That story id isn't magically going to find its way into the params[:comment] hash. You could either do
#comment = #story.comments.build(params[:comment])
#comment.user = current_user
or create the comment on the user and then set its story.