Active Admin Nested Form Edit User Information - ruby-on-rails

I have two models / resources in Raisl 4 / ActiveAdmin application.
class AdminUser < ActiveRecord::Base
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable
has_one :photographer
end
class Photographer < ActiveRecord::Base
belongs_to :admin_user, dependent: :destroy
accepts_nested_attributes_for :admin_user
end
ActiveAdmin.register Photographer do
permit_params :code, :nickname, :profile, :facebook_url, :twitter_url, :instagram_url, :address, :complement, :zip_code, :city, :state, :country,
:phone, :cellphone, :commission, :withhold_tax, :bank_number, :bank_branch_number, :bank_account_number, :identity_document_number,
:rfb_document_number, admin_user_attributes: [:email, :password, :password_confirmation]
form do |f|
f.inputs for: [:admin_user, (f.object.admin_user || f.object.build_admin_user)] do |auf|
auf.input :email
auf.input :password
auf.input :password_confirmation
end
f.inputs do
f.input :code
f.input :nickname
f.input :profile
f.input :facebook_url
f.input :twitter_url
f.input :instagram_url
f.input :address
f.input :complement
f.input :zip_code
f.input :city
f.input :state
f.input :country, as: :string
f.input :phone
f.input :cellphone
f.input :commission
f.input :withhold_tax
f.input :bank_number
f.input :bank_branch_number
f.input :bank_account_number
f.input :identity_document_number
f.input :rfb_document_number
end
f.actions
end
end
The process of creation / validation is working perfectly, however, when editing a Photographer without changing e-mail I get the error "Email has already been taken" as actually associated AdminUser record was being created and not edited.

I found the problem. For editing work properly you must also accept the Id parameter in the User attributes, otherwise it will try to create a new one.
admin_user_attributes: [:id, :email, :password, :password_confirmation]
Many thanks to #d34n5.
Strong parameters for nested attributes returns "unpermitted parameters" when empty array

Related

Ruby on Rails | one form - three tables (can't save the form content)

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.

active admin adding paren't id automatically

I'm using rails' active admin and working on a create screen for a model that belongs_to a parent. I'm getting an unpermitted_param error because activeadmin is automatically adding the parent's id to the form's parameters to be submitted. However, the parameter is being added outside of the model's hash. Here are the params submitted:
{"utf8"=>"✓",
"authenticity_token"=>"9MBGkptu3jjLd4Zoy6lLUe1r6hW9TwRAmmiUNz2SwvQapRYv8nvOqZKWZKhgn9TEIXwNiD+IheQERVs+DpUgfA==",
"wedding_cake"=>{"client_id"=>"1", "first_name"=>"bob",
"last_name"=>"smith", "address"=>"11 big circle",
"city"=>"boston", "state"=>"ma ", "zip"=>"01234",
"phone"=>"1234567890", "email"=>"", "guests"=>"150",
"time"=>"12:30pm", "special_instructions"=>"", "package"=>"lake view
pavillion", "flower_price"=>"0", "rolled_chocolate_price"=>"0",
"other_price"=>"0", "tiering_price"=>"0", "deposit"=>"50",
"balance"=>"150", "vendor_balance"=>"0", "delivery_price"=>"0",
"consultant"=>"peter", "date(1i)"=>"2019", "date(2i)"=>"11",
"date(3i)"=>"18", "slice_price"=>"3.50",
"appointment_date(1i)"=>"2018", "appointment_date(2i)"=>"10",
"appointment_date(3i)"=>"16"}, "commit"=>"Create wedding cake",
"client_id"=>"1"}
wedding_cake belongs to client and should have a client_id (which it does). However, as you can see there is another client_id outside of wedding_cake. Here is the code I am using to generate the form:
form do |f|
inputs 'Venue Info' do
f.input :client_id, :as => :hidden, :input_html => { :value => f.object.client_id }
f.input :first_name
f.input :last_name
f.input :address
f.input :city
f.input :state
f.input :zip
f.input :phone
f.input :email
end
inputs 'Cake Info' do
f.input :guests
f.input :time
f.input :special_instructions
f.input :package
f.input :flower_price
f.input :rolled_chocolate_price
f.input :other_price
f.input :tiering_price
f.input :deposit
f.input :balance
f.input :vendor_balance
f.input :delivery_price
f.input :consultant
f.input :date
f.input :slice_price
f.input :appointment_date
end
f.submit
end
my strong_parameters are set up as such:
I have my permitted_params set as such in my activeadmin registration: permit_params :client_id, :base_price, :first_name, :last_name, :address, :city, :state, :zip, :phone, :email, :guests, :time, :special_instructions, :package, :flower_price, :rolled_chocolate_price, :other_price, :tiering_price, :deposit, :balance, :vendor_balance, :delivery_price, :consultant, :date, :slice_price, :appointment_date

how to render list of children class in ruby on rails?

Hi there,
I'm starting to use Rails through a little project. All the main things are between some Doctors, patients and consultations.
I'm learning with a book to start my application and for now, it works well but i still need help for little twists!
For example, once a doctor is created, i can create a consultation but my consultation needs a patient and i don't understand how to render a list of patients in the creation of my consultation.
Does someone have a clue?
PS: This is my code
=> DOCTOR
require 'digest'
class Doctor < ActiveRecord::Base
attr_accessible :birthdate, :birthplace, :city, :country, :firstname, :id_card_no, :lastname, :mail, :password, :secu_no, :street, :street_number, :zip
attr_accessor :password
validates :birthdate, :birthplace, :city, :country, :firstname, :lastname, :id_card_no, :secu_no, :street, :street_number, :zip, :presence=>true
validates :id_card_no,:secu_no, :uniqueness=>true
validates :street_number, :zip, :numericality=>true
validates :password, :confirmation => true,
:length => { :within => 4..20 },
:presence => true,
:if => :password_required?
validates :mail, :uniqueness => true,
:length => { :within => 5..50 },
:format => { :with => /^[^#][\w.-]+#[\w.-]+[.][a-z]{2,4}$/i }
has_and_belongs_to_many :offices
has_and_belongs_to_many :specialities
has_and_belongs_to_many :secretaries
has_many :consultations
default_scope order('doctors.lastname')
before_save :encrypt_new_password
def self.authenticate(email, password)
user = find_by_email(email)
return user if user && user.authenticated?(password)
end
def authenticated?(password)
self.hashed_password == encrypt(password)
end
protected
def encrypt_new_password
return if password.blank?
self.hashed_password = encrypt(password)
end
def password_required?
hashed_password.blank? || password.present?
end
def encrypt(string)
Digest::SHA1.hexdigest(string)
end
end
=> PATIENT
class Patient < ActiveRecord::Base
attr_accessible :birthdate, :birthplace, :city, :country, :firstname, :id_card_no, :job, :lastname, :secu_no, :street, :street_number, :zip
validates :birthdate, :birthplace, :city, :country, :firstname, :lastname, :id_card_no, :secu_no, :street, :street_number, :zip, :presence=>true
validates :id_card_no,:secu_no, :uniqueness=>true
validates :street_number, :zip, :numericality=>true
has_many :consultations
default_scope order('patients.lastname')
end
=> CONSULTATION
class Consultation < ActiveRecord::Base
attr_accessible :date, :hour
validates :date, :hour, :presence=>true
belongs_to :patient
belongs_to :doctor
has_one :patient_description
has_one :consultation_file
has_and_belongs_to_many :illnesses
has_and_belongs_to_many :symptoms
end
Thanks!
Thomas
I think you want to look into a "collection_select" on the "patient_id" column of the consultation.
I really like Formtastic for this, as it "understands" your fields and e.g. creates select boxes for associations or date pickers for dates automatically:
<%= semantic_form_for #consultation do |f| %>
<%= f.inputs do %>
<%= f.input :date %>
<%= f.input :hour %>
<%= f.input :doctor %>
<%= f.input :patient %>
<% end %>
<%= f.actions do %>
<%= f.action :submit, :as => :button %>
<%= f.action :cancel, :as => :link %>
<% end %>
<% end %>
However, this is not a pure Rails solution and needs an additional Gem. I am not sure if that is okay for your training purpose.

Unknown attribute 'user_id' with devise nested attributes

I am using the Devise gem to authenticate users. I have a User model and an Address model relation where each User has_one :address and each address belongs_to :user. When I try to register a new user I get the following error on page load: unknown attribute: user_id. The trace points to the line <% resource.build_address... seen in my view.
If I just delete that line from my view the page will load but none of my nested form fields show up.
In Rails console I can create and save an address then use that saved address as an attribute for a new User that will save.
The view is as follows:
<% resource.build_address unless resource.address %>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= f.email_field :email, :autofocus => true, placeholder: "Your email", class: 'input-block-level' %><br>
<%= f.password_field :password, placeholder: "Password", class: 'input-block-level' %><br>
<%= f.password_field :password_confirmation, placeholder: "Confirm password", class: 'input-block-level' %><br>
<%= f.text_field :favorite_cuisine, placeholder: "Favorite cuisine", class: 'input-block-level' %><br>
<%= f.fields_for :address do |address_form| %>
<%= address_form.text_field :street_one, placeholder: "Street", class: 'input-block-level' %><br>
<%= address_form.text_field :street_two, placeholder: "Street #2", class: 'input-block-level' %><br>
<%= address_form.text_field :city, placeholder: "City", class: 'input-block-level' %><br>
<%= address_form.text_field :state, placeholder: "State", class: 'input-block-level' %><br>
<%= address_form.text_field :zip, placeholder: "zip", class: 'input-block-level' %><br>
<% end %>
<% end %>
My User model:
has_one :address, :dependent => :destroy
accepts_nested_attributes_for :address
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me,
:favorite_cuisine, :username, :address
validates_presence_of :email
validates_presence_of :address
My Address model:
belongs_to :user
attr_accessible :city, :state, :street_one, :street_two, :zip, :user_id
validates_presence_of :city
validates_presence_of :state
validates_presence_of :street_one
validates_presence_of :zip
Where am I going wrong here?
rails g migration AddUserIdToAddresses
Then edit the file, and
def change
add_column :addresses, :user_id, :integer
end
then rake db:migrate
Try something like this:
<%= f.fields_for (resource.address || :address), ... %>
Because the form is nested, it should build a new one with form submission to my knowledge.

mass assignment selecting childs of user, using Devise

I have a very simple issue:
User model:
class User < ActiveRecord::Base
devise :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :id, :email, :password, :password_confirmation, :remember_me,
:firstname, :lastname, :mobile_phone, :user_type, :department_id, :department_attributes
belongs_to :department
accepts_nested_attributes_for :department, :allow_destroy => false
Departments model:
class Department < ActiveRecord::Base
has_many :users
accepts_nested_attributes_for :users, :allow_destroy => true
I created a form to be able to select my departments member from my existing users using simple_form:
<%= simple_form_for #department, :validate => true do |form| %>
<%= form.error_messages %>
<%= form.association :users, :prompt => 'assign a user', :label => 'User'%>
<%= form.button :submit %>
<% end %>
Then I (try to) update my users via the department controller:
def update
#department = Department.find(params[:id])
respond_to do |format|
if #department.update_attributes(params[:department])
...
This generates following error:
WARNING: Can't mass-assign protected attributes: user_ids
My guess is that some devise settings generate this error but I don't know which ones.
Can you help? Thanks!
Add attr_accessible :user_ids to your Department model.

Resources