NameError in Roles#new , undefined local variable or method `permissions' - ruby-on-rails

i'm doing role and permission. I want to add a permission checkbox to role create page, so when admin create role can tick the permission checkbox then store at role_permission.
I want the checkbox can connect with the permission_id because when i create one permission it will also show at the role create page.
Now i want to show the checkbox at the role create page but it give me some error.
role controller
def new
#role = Role.new
#role.company_id = params[:company_id]
#permission = Permission.all
end
def create
#role = Role.new(role_params)
#company_id = Company.find(params[:role][:company_id])
#permission_id = Permission.all
if #role.save
flash[:success] = "Succesful create!"
redirect_to #role
else
render 'new'
end
end
private
def role_params
params.require(:role).permit(:name, :company_id)
end
new.html.erb
<% provide(:title, "Create Roles") %>
<h1>Create Role</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: #role, local: true) do |f| %>
<%= permissions.each do |permission|%>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :permission_id %>
<%= f.check_box_tag 'permission_ids[]', permission.id, false%>
<%= f.hidden_field :company_id , value: 2%>
<%= f.submit "Create Role", class: "btn btn-primary" %>
<% end %>
<% end %>
</div>
error show in website
error show in console
Update
error show after update

In a controller, the variable name should be plural as its array/multiple records.
def new
...
...
#permissions = Permission.all
end
And in a view we can use the same as below:
<%= #permissions.each do |permission|%>
<%= render 'shared/error_messages', object: f.object %>
Checkbox seems ok, but if you want to dig more, then can have a look at here: https://apidock.com/rails/v6.0.0/ActionView/Helpers/FormTagHelper/check_box_tag

Related

Ruby on Rails: Populate dropdown with two fields of database record

In my database I have a Users table that looks something like:
User_ID Firstname Surname Company
1 Steve Jobs Apple
2 Bill Gates Microsoft
What I am trying to do is make a drop down menu in a form that would allow a user to choose from selecting their name or their company, e.g. when Steve Jobs is logged in he can either select "Steve" or "Apple" in the drop down menu.
What I have tried so far is the following:
<%= f.select :from_name, [session[:user_id],session[:user_id]] %>
Which obviously didn't work because it only returns the user id of the logged in user.
<%= f.select :from_name, [#user.firstname,#user.company] %>
Which gave me the error undefined methodfirstname for nil:NilClass`
My Users controller is as follows:
class UsersController < ApplicationController
before_filter :check_authorization, :except => [:show, :new, :create, :search ]
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
#user.role = "customer"
if #user.save
session[:user_id] = #user.id
# Save a copy of the email address entered by the user into the Accounts table
#account = Account.create(email: params[:user][:primaryemailaddress], user_id: session[:user_id])
redirect_to root_path
else
render 'new'
end
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to #user
else
render 'edit'
end
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to users_path
end
private
def user_params
params.require(:user).permit(:title, :firstname, :surname, :housenumber, :street, :city, :postcode, :company, :primaryemailaddress, :password)
end
end
And my _form.html.erb is:
<%= form_for(#email) do |f| %>
<% if #email.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#email.errors.count, "error") %> prohibited this email from being saved:</h2>
<ul>
<% #email.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :from_name %><br>
<%= f.select :from_name, [current_user.firstname, current_user.company] %>
</p>
<p>
<%= f.label :From_Email_Address %><br>
<%= f.collection_select :account_id, Account.where(user_id: session[:user_id]),
:id,:email %>
</p>
<p>
<%= f.label :to %><br>
<%= f.text_field :to %>
</p>
<p>
<%= f.label :cc %><br>
<%= f.text_field :cc %>
</p>
<p>
<%= f.label :bcc %><br>
<%= f.text_field :bcc %>
</p>
<p>
<%= f.label :subject %><br>
<%= f.text_field :subject %>
</p>
<p>
<%= f.label :message %><br>
<%= f.text_field :message %>
</p>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I'm not too sure how to solve this issue, can someone please help.
#BenSmith I guess you are accessing EmailsController. And on that controller's new or edit method there is no #user variable.
In your edit and new method add
#user = User.find(session[:user_id])
undefined method firstname for nil:NilClass
Seems like some how #user is nil
create a helper and check for presence of #user
<%= f.select :from_name, dropdown_values %>
application_helper.rb
def dropdown_values
if #user.present?
[#user.firstname, #user.company]
else
['default', 'values']
end
end
<p>
<%= f.label :from_name %><br>
<%= f.select :from_name, [current_user.firstname, current_user.company] if #user.present?%>
</p>
because User.new time create blank object doesn't find username.i hope its will be help you.

Add a join key to a group

I'm creating an app to store game results between friends. In my app groups will be called Leagues.
To keep the leagues private I'd like to add a join key to it. When a league is created the creator chooses a join key. Later other users can join by choosing a league from a dropdown and filling in the exact join key. The user can only if the join key matches the selected league.
Controller:
def edit
#user = User.find(current_user.id)
#league_list = League.all.map{|l| [ l.league_name, l.id ] }
# #league_keys = League.all.map{|l| [ l.join_key, l.id ] }
end
def update
#user = User.find(current_user.id)
if #user.update(user_join_league_params) #&& #league_list.league_id == #league_keys.league_id
#user.save
redirect_to root_path, :notice => "Successfully joined this league!"
else
render 'index'
end
end
As you can see I have to edit the users league_id to complete the join.
View:
<div class="panel panel-default" style="margin-right:10px; margin-left:10px; text-align:center">
<div class="panel-heading">
JOIN A LEAGUE
</div>
<div class="panel-body">
<%= simple_form_for(#user) do |f| %>
<%= f.select(:league_id, #league_list) %><br> <br>
# <%= f.input_field :join_key %><br> <br>
<p>!! Watch out this cannot be changed after !!</p>
<br> <br> <%= f.submit "Join league", class: "btn-submit" %>
<% end %>
</div>
</div>
So I'd like this form to only perform the update action if the selected league matches the filled in key.
I've been looking for an answer in numerous posts on stackoverflow but I couldn't find a post with a simular issue.
How can I get this done?
EDIT:
Relations:
class User < ActiveRecord::Base
belongs_to :league
end
class League < ActiveRecord::Base
has_many :games
has_many :multiplayergames
has_many :users
end
SECOND EDIT:
So I've tried to implement the solloution.
I was using simple_form for <%= f.select(:league_id, #league_list) %>
I tried to do it like this:
<%= form_tag(user_path(#user), method: :put) do %>
<%= select_tag :league_id, options_for_select(#league_list) %><br> <br>
<p>Join Key</p>
<%= text_field_tag :join_key %><br> <br>
<p>!! Watch out this cannot be changed after !!</p>
<br> <br> <%= submit_tag "Join league", class: "btn-submit" %>
<% end %>
However this gives the error:
param is missing or the value is empty: user
THIRD EDIT:
Controller:
# JOIN A LEAGUE
def edit
#user = User.find(current_user.id)
#league_list = League.all.map{|l| [ l.league_name, l.id ] }
end
def update
#user = User.find(current_user.id)
#league = League.find_by_id(params[:league_id])
if #league.join_key == params[:join_key] && #user.update(user_join_league_params)
redirect_to root_path, :notice => "Successfully joined this league!"
else
redirect_to edit_user_path(current_user), notice: "Could not join league check if join key is correct!"
end
end
def user_join_league_params
params.permit!(:league_id,:join_key)
end
VIEW:
<%= form_tag(user_path(#user), method: :put) do %>
<%= select_tag :league_id, options_for_select(#league_list, :league_id) %><br> <br>
<p>Join Key</p>
<%= text_field_tag :join_key %><br> <br>
<p>!! Watch out this cannot be changed after !!</p>
<br> <br> <%= submit_tag "Join league", class: "btn-submit" %>
<% end %>
update action can look as follows:
def update
#user = User.find(current_user.id)
#league = League.find_by_id(params[:league_id])
if #league.join_key == params[:join_key] && #user.update(league_id: params[:league_id])
redirect_to root_path, :notice => "Successfully joined this league!"
else
render 'index'
end
end
form can look as follows:
<%= form_tag(user_path(#user), method: :put) do %>
<%= select_tag :league_id, options_for_select(#league_list) %><br> <br>
<%= text_field_tag :join_key %><br> <br>
<p>!! Watch out this cannot be changed after !!</p>
<br> <br> <%= submit_tag "Join league", class: "btn-submit" %>
<% end %>
Note: I have assumed join_key is an attribute in your League model.
Make sure you pass params accordingly in your user_join_league_params.
Edit:
Your should permit your params:
def user_join_league_params
params.permit!(:league_id,:join_key)
end

sign up and create new object at the same time

i'm new in Ruby on Rails.
I was trying to register a new user with devise and at the same time, create a new Company object. The association between them : User belongs to Company. Company has many users. I tried to make it based on this link : http://railscasts.com/episodes/196-nested-model-form-part-1?view=asciicast, but it didnt work. it said : "undefined method for Company", which is Company doesnt have email attribute.
and in sign up form, i only put email attribute for user
<div class="title"><%= t('.signup') %></div>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="control-group"><%= f.label :email, t('.email') %>
<%= f.email_field :email %></div>
<div class="control-group"><%= f.label :password, t('.password') %>
<%= f.password_field :password %></div>
<div class="control-group"><%= f.label :password_confirmation, t('.password_confirmation') %>
<%= f.password_field :password_confirmation %></div>
<%= f.fields_for :company_attributes do |f_company| %>
<div class="control-group"><%= f_company.label :name, t('.company_name') %>
<%= f_company.text_field :name %></div>
<% end %>
<div class="buttons"><%= f.submit t('.signup'), class:"btn btn-primary" %><br>
<%= render "links" %></div>
<% end %>
updated
Company controller :
class CompaniesController < Devise::RegistrationsController
def new
#company = Company.new
#user = #company.users.build
end
def create
#company = Company.new(params[:company])
#user = User.create(params[:user].merge(company_id:company.id))
if #company.save
redirect_to "/"
else
render 'users/sign_up'
end
end
end
User Controller :
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to users_path
else
render 'users/new'
end
end
I would really appreciate any idea and any help. Thanks in advance
In your case, since you are only interested in receiving the company_name I'd simplify it and submit the company_name via a text_field_tag.
In other words, I would replace:
<%= f.fields_for :company_attributes do |f_company| %>
<div class="control-group"><%= f_company.label :name, t('.company_name') %>
<%= f_company.text_field :name %></div>
<% end %>
With this
<%= text_field_tag 'company_name', {placeholder:"Enter here the name of your company",class:"form-control"} %>
This would submit the name to the UsersController, and you could access it with params[:company_name] so the controller would look like this:
Users controller:
def new
#user = User.new
end
def create
#user = User.create(params[:user])
#Create a company via 'user<->company' association using 'company_name'
#company= #user.company.create(name: params[:company_name])
if #user.save
redirect_to users_path
else
render 'users/new'
end
end

Assigning values to attributes in the background during form submission with Rails

I have a form on a page that a user can use to create a course. While I understand how to get provide the user the opportunity to fill in simple things like the course name and description, I also want to assign the user's id to a teacher_id column. This should be done automatically for the user and they shouldn't see an opportunity to assign a teacher_id as it should be their id.
Currently the "Create a course" page's view is this:
<% provide(:title, 'My Classes') %>
<h1>Create a class!</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#course) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description, :size => "30x6" %>
<!-- Assign the current user's id to the teacher_id column in the background -->
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
And the new action in the course controller looks like:
def new
#course = Course.new
end
What's the best way to accomplish what I want to do? I'm pretty new to Rails and I haven't had much experience with forms and all the possibilities. I read a little bit on the hidden_field_tag but I don't know if that's the kind of thing I need and I was finding it difficult to get the user's id in the form anyway. Do I need to make a user instance variable in the controller or can I do it with code in the view somehow.
Thanks for the help.
You can use the hidden_field:
<% provide(:title, 'My Classes') %>
<h1>Create a class!</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#course) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description, :size => "30x6" %>
<%= f.hidden_field :teacher_id, :value => :current_user.id %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
EDIT - to explain how to have the current_user available in the form.
I normally have a session controller that is responsible for login and logout users, creating a session to keep the user logged in.
The create action for example:
def create
user = User.find_by_name(params[:name])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
flash[:success] = "Welcome " + current_user.name
redirect_to user
else
flash.now[:error] = "Invalid username/password combination."
render "new"
end
end
If the combination of username and password are correct, it will create a session with the user_id (session[:user_id]).
Now, in your application_controller you can have something like the below:
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
The helper_method allows you to use the current_user in any controller or view in your application.
I hope it helps....
You would probably have a create action like:
def create
#course = Course.new(params[:course])
end
Assuming you have the variable for the #current_user available, you should be able to set that in the controller before you save the new Course.
def create
#course = Course.new(params[:course])
#course.teacher_id = #current_user.id
#course.save
redirect_to :action => "show", :id => #course.id
end

Using Wicked with Devise for a sign up wizard

I am using devise with wicked to create a sign up wizard, but I am unsure about a problem I am having creating profiles. After a user provides their email & password they are forwarded to a step to create a profile based on whether they have specified they are a shipper or carrier. However I am unsure what the code should be in the controller and the forms to generically create a profile. Here is the code I have for the application:
The steps controller:
class UserStepsController < ApplicationController
include Wicked::Wizard
steps :carrier_profile, :shipper_profile
def create
#user = User.last
case step
when :carrier_profile
#profile = CarrierProfile.create!(:dot => params[:dot])
if #profile.save
render_wizard #user
else
flash[:alert] = "Record not saved"
end
when :shipper_profile
#profile = ShipperProfile.create!(params[:shipper_profile)
if #profile.save
render_wizard #user
else
flash[:alert] = "Record not saved"
end
end
end
end
end
def show
#user = User.last
#carrier_profile = CarrierProfile.new
#shipper_profile = ShipperProfile.new
case step
when :carrier_profile
skip_step if #user.shipper?
when :shipper_profile
skip_step if #user.carrier?
end
render_wizard
end
end
The form for a carrier profile:
<% form_for #carrier_profile , url: wizard_path, method: :post do |f| %>
<div>
<%= f.label :dot, "Please enter your DOT Number:" %>
<%= f.text_field :dot %>
</div>
<%= f.submit "Next Step", class: "btn btn-primary" %>
<% end %>
The form for a shipper profile:
<% form_for #shipper_profile , url: wizard_path, method: :post do |f| %>
<div>
<%= f.label :company_name, "What is your company name?" %>
<%= f.text_field :company_name %>
</div>
<%= f.submit "Next Step", class: "btn btn-primary" %>
<% end %>
The user model:
class User < ActiveRecord::Base
has_one :carrier_profile
has_one :shipper_profile
end
How would I be able to write a generic new and create method to handle creating both profiles? With the current code it is stating that the user_steps controller has no POST method, although if I run rake routes I find that this is untrue.
Add a step :profile_select to find which profile should be created
class UserStepsController < ApplicationController
include Wicked::Wizard
steps :profile_select, :carrier_profile, :shipper_profile
def update
#user = current_user
case step
when :profile_select
if params[:user][:profile_type] == 'carrier'
#profile = current_user.carrier_profile.build
else
#profile = current_user.shipper_profile.build
end
when :carrier_profile
current_user.carrier_profile.update_attributes(params[:carrier_profile])
when :shipper_profile
current_user.shipper_profile.update_attributes(params[:shipper_profile])
end
render_wizard #user
end
def show
#user = current_user
case step
when :carrier_profile
skip_step if #user.shipper?
when :shipper_profile
skip_step if #user.carrier?
end
render_wizard
end
end
views/user_steps/profile_select.html.erb:
Note: method :put so that update gets called for all steps
<%= form_for current_user, url: wizard_path, method: :put do |f| %>
<%= f.label :profile_type %>
<%= f.text_field :profile_type %>
<%= f.submit "Next Step", class: "btn btn-primary" %>
<% end %>
views/user_steps/carrier_profile.html.erb:
<% form_for #profile, url: wizard_path, method: :put do |f| %>
<div>
<%= f.label :dot, "Please enter your DOT Number:" %>
<%= f.text_field :dot %>
</div>
<%= f.submit "Next Step", class: "btn btn-primary" %>
<% end %>
views/user_steps/shipper_profile.html.erb:
<% form_for #profile, url: wizard_path, method: :put do |f| %>
<div>
<%= f.label :company_name, "What is your company name?" %>
<%= f.text_field :company_name %>
</div>
<%= f.submit "Next Step", class: "btn btn-primary" %>
<% end %>

Resources