mass assignment selecting childs of user, using Devise - ruby-on-rails

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.

Related

Create devise user and profile model with same form in rails

I'm looking to create a form with input fields for two models - Devise User model and Profile model. I want the profile model to be created with the fields and reference the User model when created.
Registration New view
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<!-- Devise Fields for User model -->
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
<%= f.password_field :password, autocomplete: "new-password" %>
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
<!-- Profile model -->
<%= f.fields_for :profile do |g| %>
<%= g.text_field :first_name %>
<%= g.text_field :last_name %>
<% end %>
<%= f.submit "Sign up" %>
<% end %>
User Model
has_one :profile, dependent: :destroy
attr_accessor :first_name, :last_name
accepts_nested_attributes_for :profile
Profile Model
belongs_to :user
Application Controller
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [ profile_attributes: [:first_name, :last_name]])
end
Devise Registration controller (override)
def new
super do |resource|
resource.build_profile
end
end
After filling out the form I receive an error message. Refer to the following image
Here is the code on Github https://github.com/Goeken/Speech-today
How should I go about this?
I had look into your github repository code & I found that your User model code is not correct. Here's the modified user model -
class User < ApplicationRecord
has_one :profile, dependent: :destroy
# You should not add first_name last_name validation message here,
# because those are profile model attributes, Not user model
#validates_presence_of :first_name, :last_name
accepts_nested_attributes_for :profile
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
And rest of code are OK.
I hope it will work.

has_one belongs_to association attribute validation

I use devise for user authentication. Have two models User and Profile which are associated to each other like this
#app/model/user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_one :profile, dependent: :destroy
enum role: [:admin, :seller, :buyer]
end
#app/model/profile.rb
class Profile < ApplicationRecord
belongs_to :user
end
As you can see I have also role for users.
Here is forms for registrations of both models.
#user registration form
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
...
<%= f.select :role, collection: User.roles.keys.last(2) %>
<%= f.input :mobile_number, required: true, autofocus: true %>
...
<% end %>
#profile registration form
<%= simple_form_for(#profile) do |f| %>
...
<% if current_user.seller? %>
<%= f.input :location, required: true %>
<% else %>
<%= f.input :company_code, required: true %>
<% end %>
...
<% end %>
Problem
When current user is seller I need to validate presence of :location , when user is buyer then validate presence of :company_code.
How can I achieve that? I appreciate any helps , Thanks!
validates method accepts if option:
# app/model/profile.rb
class Profile < ApplicationRecord
belongs_to :user
validates :location, presence: true, if: "user.seller?"
validates :company_code, presence: true, if: "user.buyer?"
end
Also, current_user.role == "seller" is obsolete. Rails automatically sets up additional methods in model for enum option values, therefore you may just write: current_user.seller?, etc.

Active Admin Nested Form Edit User Information

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

One to One relation between tables in Rails

Just started my first project in ROR and i'm facing a problem with build a relation between table.
As a noob i search a lot around the web, try plenty of stuff but can't figure out how to get this working.
Here's my issue: I built a User table for the login function - made with devise, now i want to build another table UserMeta to carry all the profile info of my users.
Here is the code of what i did:
app/models/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
attr_accessible :email, :encrypted_password
has_one :user_meta
end
*app/models/user_meta.rb*
class UserMeta < ActiveRecord::Base
attr_accessible :admin, :birthday, :company, :first_name, :job, :last_name, :phone, :rfid, :statut, :website, :user_id
belongs_to :users
end
class User
has_one :user_meta
end
*app/controllers/user_controllers.rb*
def new
#user = User.new
#meta = UserMeta.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
app/views/users/new.html.erb
<%= form_for(#meta) do |f| %>
<div class="field">
<%= f.label :phone %><br />
<%= f.text_field :phone %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
It returns :
undefined method `meta_index_path' for #<#<Class:0x000001016f3f18>:0x00000100e9f6f0>
I know there is one or many mistake, what the best way to do this ? Some help will be appreciated :)
You can change to like this:
app/models/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :encrypted_password
has_one :user_meta
accepts_nested_attributes_for :user_meta
end
app/models/user_meta.rb
class UserMeta < ActiveRecord::Base
attr_accessible :admin, :birthday, :company, :first_name, :job, :last_name, :phone, :rfid, :statut, :website, :user_id
belongs_to :user
end
app/controllers/user_controllers.rb
def new
#user = User.new
#user.build_meta_user
respond_to do |format|
format.html
format.json { render json: #user }
end
end
app/views/users/new.html.erb
<%= form_for #user, :url => {:action => 'create'} do |f| %>
<!-- User related fields -->
<%= f.fields_for :user_meta do |meta_f| %>
<div class="field">
<%= meta_f.label :phone %><br />
<%= meta_f.text_field :phone %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
In Rails it's best to name your classes the same as your filenames. So app/models/user_meta.rb should be class UserMeta < ActiveRecord::Base.
There's no need to re-open the User-class in app/models/user_meta.rb. He'll know about app/models/user.rb already.
Change your belongs_to :users to belongs_to :user
In app/models/user.rb you can drop the 2nd attr_accessible :email.

many to many association

So I have a model below that represents the situation:
Students participate in Contests.
Contests measure certain skills.
For each contest, each student gets a score for each skill measured.
Here are my models:
class Student < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :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
attr_accessible :name
has_and_belongs_to_many :skills
has_many :contest_participations
has_many :contests, :through => :contest_participations
has_many :contest_scores, :through => :contests
end
class Skill < ActiveRecord::Base
attr_accessible :name
has_and_belongs_to_many :students
end
class Contest < ActiveRecord::Base
attr_accessible :name, :contest_participations_attributes, :contest_scores_attributes
has_many :contest_participations
has_many :students, :through => :contest_participations
has_many :contest_skills
has_many :skills, :through => :contest_skills
has_many :contest_scores
accepts_nested_attributes_for :contest_participations, :contest_scores
end
class ContestParticipation < ActiveRecord::Base
attr_accessible :contest_id, :student_id
belongs_to :student
belongs_to :contest
end
class ContestScore < ActiveRecord::Base
attr_accessible :contest_id, :score, :skill_id, :student_id
has_and_belongs_to_many :contests
has_and_belongs_to_many :skills
has_and_belongs_to_many :student
end
In my contests edit view, I'm trying to create a form, with formtastic, that will show all contest participants, and allow the user to add a score for each skill in the contest as follows.
But I get an error (student_id invalid symbol). How can I update the student scores?
<%= semantic_form_for #contest do |f| %>
<%= f.input :name %>
<%= #contest.students.each do |student| %>
<%= #contest.skills.each do |skill| %>
<%= f.inputs :name => "Scores", :for => :contest_scores do |scores_form| %>
<%= scores_form.input :student_id => "student.id" %>
<%= scores_form.input :skill_id => "skill.id" %>
<%= scores_form.input :score, :label => "Score" %>
<% end %>
<br />
<% end %>
<% end %>
<%= f.actions do %>
<%= f.action :submit, :as => :button %>
<% end %>
<% end %>
Try this. Added hidden because e think you don't want ids to show up
<%= scores_form.input :student_id, :as => :hidden, :value => student.id %>
<%= scores_form.input :skill_id, :as => :hidden, :value => skill.id %>

Resources