Model does not seem to be getting saved? - ruby-on-rails

So I am using the devise gem to generate users for my web app. I have a Business model that is a has_one: association with my User. When I attempt to create a business when logged into my user it simply does not save it. Also when i use rails console in the terminal attempting to open up my Business model returns nil. In the view that is calling .business on the user shows nothing
Here is my business model
class Business < ActiveRecord::Base
belongs_to :user
end
User Model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates :name, presence: true
has_many :posts, dependent: :destroy
has_one :business, dependent: :destroy
has_attached_file :avatar,
styles: { medium: "300x300#", thumb: "100x100#", post_pic: "44x44" },
default_url: "/images/:style/missing.png"
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/
end
Business controller
class BusinessesController < ApplicationController
before_action :set_business, only: [:show, :edit, :update, :destroy]
def index
#businesses = Business.all
end
def show
end
def new
#business = current_user.build_business
end
def edit
end
def create
#business = current_user.build_business(business_params)
if #business.save
redirect_to #business, notice: 'Business was successfully created.'
else
render :new
end
end
def update
if #business.update(business_params)
redirect_to #business, notice: 'Business was successfully updated.'
else
render :edit
end
end
def destroy
#business.destroy
redirect_to businesses_url, notice: 'Business was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_business
#business = Business.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def business_params
params.require(:business).permit(:name, :desc, :avatar)
end
end
VIEW THAT CALLS THE BUSINESS
<div class="row">
<div class="col-md-7">
<div class="panel panel-default">
<div class="panel-body">
<%= image_tag current_user.business.avatar.url(:thumb), class:"img-thumbnail" %>
<%= current_user.business.name %>
<%= current_user.business.desc %>
<%= link_to 'create business', new_business_path, class:"pull-right" %>
</div>
</div>
</div>
</div>

Do you have a user_id column in your business table? It would look like this: t.integer "user_id"
Then, to directly associate the business with the user, in businesses_controller.rb I would write the new and create methods in that way:
def new
#business = current_user.businesses.new
end
def create
#business = current_user.businesses.new(business_params)
if #business.save
redirect_to #business, notice: 'Business was successfully created.'
else
render :new
end
end
Hope this helps.

Related

Rails: NoMethodError on creating has_one association with devise model

I am a complete beginner in Rails as such and I am trying to build a page to add extra profile data once the user logs in.
I am using Devise for authentication purposes and that works fine. I get this error and I have been stuck here.
undefined method `profiles'
Can you please help?
Codes
profiles_controller.rb
class ProfilesController < ApplicationController
before_action :authenticate_user!, only: [:new, :create, :show]
def new
#profile = current_user.profiles.build
end
def create
#profile = current_user.profiles.build(profile_params)
if #profile.save
format.html {redirect_to #profile, notice: 'Post was successfully created.'}
else
format.html {render 'new'}
end
end
def show
#profile = current_user.profiles
end
private
def profile_params
params.require(:profile).permit(:content)
end
end
The error seems to be coming from these lines in particular
def new
#profile = current_user.profiles.build
end
Other codes for reference:
/views/profiles/new.html.erb
<h1>Profiles#new</h1>
<p>Find me in app/views/profiles/new.html.erb</p>
<h3>Welcome <%= current_user.email %></h3>
<%= form_for(#profile) do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :text, autofocus: true %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<%end%>
routes.rb
Rails.application.routes.draw do
get 'profiles/new'
get 'profiles/create'
get 'profiles/show'
get 'profiles/update'
get 'pages/home'
get 'pages/dashboard'
devise_for :users, controllers: { registrations: "registrations" }
resources :profiles
root 'pages#home'
devise_scope :user do
get "user_root", to: "page#dashboard"
end
end
models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_one :profile, dependent: :destroy
end
models/profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
end
I just figured it out!
As the relationship is has_one, we should be using
def new
#profile = current_user.build_profile
end
instead of
def new
#profile = current_user.profiles.build
end
according to the documentation -
http://guides.rubyonrails.org/association_basics.html#has-one-association-reference
1) If your user must have many profiles. Set in your app/models/user.rb has_many :profiles
2) In your ProfilesController in new method instead of #profile = current_user.profiles use #profile = Profile.new
3) In your routes.rb delete
get 'profiles/new'
get 'profiles/create'
get 'profiles/show'
get 'profiles/update'
because you have already used resources :profiles
4) To stay with rules of DRY you can render form from a partial. Just add in views/profiles/_form.html.erb with the same content in your new.html.erb and after this you can delete everything im new.htm.erb and paste <%= render "form" %>. In future it will help you to render edit form if you want.
5) In your ProfilesController you can add method index with all profiles
def index
#profiles = Profile.all
end
You are trying to call an undefined relationship:
def new
#profile = current_user.profiles.build
end
has_one :profile
You should be calling:
def new
#profile = current_user.build_profile
end

Rails - nested model input data not appearing in "show" page

I am having trouble figuring out how to make some data collected through a nested model appear on the "show" page. I have a rails app with 3 models, a User model, a Project model, and a Team model. The model associations are as follows:
Project:-
class Project < ActiveRecord::Base
has_many :users, :through => :team
has_one :team, :dependent => :destroy
accepts_nested_attributes_for :team, allow_destroy: true
end
Team:-
class Team < ActiveRecord::Base
belongs_to :project
has_many :users
end
User:-
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_and_belongs_to_many :teams
end
Every project has one team, and every team consists of many users who are already saved in the database. What I would like to do exactly is to make it possible to select multiple existing users within the project form (through a nested form) and save them to a model called team. I managed to get the form working correctly, but im not sure how to go about saving the data collected to the team model, and then to make the group of users that were selected (the team) to appear in project's show page. Please help!
P.S I used the nested form gem to add multiple team members within the project's form.
Projects Show page:-
<%= bootstrap_nested_form_for(#project, :html => {:multipart => true}, layout: :horizontal) do |f| %>
<% f.fields_for :teams do |builder| %>
<% if builder.object.new_record? %>
<%= builder.collection_select :user, User.all, :id, :email, { prompt: "Please select", :selected => params[:user], label: "Employee" } %>
<% else %>
<%= builder.hidden_field :_destroy %>
<%= builder.link_to_remove "Remove" %>
<% end %>
<%= f.link_to_add "Add Team Member", :teams %>
<%= f.submit %>
<% end %>
projects controller:-
class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#projects = Project.all
respond_with(#projects)
end
def show
respond_with(#project)
end
def new
#project = Project.new
#project.pictures.build
#project.teams.build
respond_with(#project)
end
def edit
#project = Project.find(params[:id])
#project.pictures.build
#project.teams.build
end
def create
#project = Project.new(project_params)
if #project.save
flash[:notice] = "Successfully created project."
redirect_to #project
else
render :action => 'new'
end
end
def update
#project.update(project_params)
respond_with(#project)
end
def destroy
#project.destroy
respond_with(#project)
end
private
def set_project
#project = Project.find(params[:id])
end
def project_params
params.require(:project).permit(:id, :title, :description, :status, :phase, :location, :image, pictures_attributes: [:id, :image], teams_attributes: [:project_id, :user_id])
end
end

Rails - Nested form not showing on "show" page

I am having trouble figuring out how to make some data collected through a nested model appear on the "show" page. I have a rails app with 3 models, a User model, a Project model, and a Team model. The model associations are as follows:
Project:-
class Project < ActiveRecord::Base
has_many :users, :through => :team
has_one :team, :dependent => :destroy
accepts_nested_attributes_for :team, allow_destroy: true
end
Team:-
class Team < ActiveRecord::Base
belongs_to :project
has_many :users
end
User:-
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_and_belongs_to_many :teams
end
Every project has one team, and every team consists of many users who are already saved in the database. What I would like to do exactly is to make it possible to select multiple existing users within the Project form (through a nested form) and save them to a model called Team. I managed to get the form working correctly, but im not sure how to go about saving the data collected to the team model, and then to make the group of users that were selected (the team) to appear in project's show page, as there are 3 models involved. The Please help!
P.S I used the nested form gem to add multiple team members within the project's form.
Projects Show page:-
<%= bootstrap_nested_form_for(#project, :html => {:multipart => true}, layout: :horizontal) do |f| %>
<% f.fields_for :teams do |builder| %>
<% if builder.object.new_record? %>
<%= builder.collection_select :user, User.all, :id, :email, { prompt: "Please select", :selected => params[:user], label: "Employee" } %>
<% else %>
<%= builder.hidden_field :_destroy %>
<%= builder.link_to_remove "Remove" %>
<% end %>
<%= f.link_to_add "Add Team Member", :teams %>
<%= f.submit %>
<% end %>
projects controller:-
class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#projects = Project.all
respond_with(#projects)
end
def show
respond_with(#project)
end
def new
#project = Project.new
#project.pictures.build
#project.teams.build
respond_with(#project)
end
def edit
#project = Project.find(params[:id])
#project.pictures.build
#project.teams.build
end
def create
#project = Project.new(project_params)
if #project.save
flash[:notice] = "Successfully created project."
redirect_to #project
else
render :action => 'new'
end
end
def update
#project.update(project_params)
respond_with(#project)
end
def destroy
#project.destroy
respond_with(#project)
end
private
def set_project
#project = Project.find(params[:id])
end
def project_params
params.require(:project).permit(:id, :title, :description, :status, :phase, :location, :image, pictures_attributes: [:id, :image], teams_attributes: [:project_id, :user_id])
end
end

Rails 4 - how to get user name from their id

I have a order show page shown below. I had this working but ever since I changed computers to work on this app, the name did not display.
If I change <%= #order.user.name %> to <%= #order.user.id %>, I get the correct id. Otherwise I get nothing displaying where as the name of the id should be posted.
#view/orders/show.html.erb
<p>
<strong>Code:</strong>
<%= #order.code %>
</p>
<p>
<strong>Client:</strong>
<%= #order.client.name %>
</p>
<p>
<strong>User:</strong>
<%= #order.user.name %>
</p>
<p>
<strong>Notes:</strong>
<%= #order.memo %>
</p>
<p>
<strong>Status:</strong>
<%= #order.status ? "Confirmed" : "In Progress" %>
</p>
<%= link_to 'Edit', edit_order_path(#order) %> |
<%= link_to 'Back', orders_path %>
#models/order.rb snippet
class Order < ActiveRecord::Base
belongs_to :user
end
#model/user.rb
class User < ActiveRecord::Base
has_many :orders, dependent: :destroy
has_many :addresses, dependent: :destroy
has_many :telephones, dependent: :destroy
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
enum role: [:user, :manager, :admin]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
end
end
#controllers/order_controller.rb snippet
def create
#order = Order.new(order_params)
#order.user_id = current_user.id
#order.status = TRUE
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render :show, status: :created, location: #order }
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
I think I just answered another question of yours, but I would recommend using the .delegate method like this:
#app/models/order.rb
Class Order < ActiveRecord::Base
belongs_to :user
delegate :name, to: :user, prefix: true #-> #order.user_name
end
You can delegate multiple variables if you need to.
This fixes Law of Dementer, as described here
As mentioned in comments, the value for the user name is empty and that is why it displays a blank when looking for the name.
Adding a name(string) to the user.name will solve the issue
When using a different database, make sure to also update the database with data, preferably the same data which initially tested with.
It's completely independent of the machine you use, so there have to be some changes you've made in your code that you don't remember.
Check what value is returned when you call this user from the console. Type rails c in the terminal and then type a command:
User.find(<<ID_OF_USER_WHOES_NAME_IS_NOT_DISPLAYED>>).name
If its name is empty, it could be a problem with creating a user or something.
Make update when you'll check it.

How to update data in join table in Rails 4

I am building an app with Rails 4 using Devise and CanCan. When a new user registers they are not given a default role. The admin has to manually assign it through the admin panel. And that's where I am running into difficulty. I can't figure out how to update the data in the join field. Here's what I have so far.
My UsersController:
class UsersController < ApplicationController
before_filter :authenticate_user!
before_action :set_user, only: [:show, :update, :destroy]
def index
authorize! :index, #user, message: 'Not authorized as an administrator.'
#users = User.all
end
def show
end
def update
authorize! :update, #user, message: 'Not authorized as an administrator.'
if #user.update_attributes(user_params)
redirect_to users_path, notice: "User updated."
else
redirect_to users_path, alert: "Unable to update user."
end
end
def destroy
authorize! :destroy, #user, message: 'Not authorized as an administrator.'
unless #user == current_user
#user.destroy
redirect_to users_path, notice: "User deleted."
else
redirect_to users_path, notice: "Can't delete yourself."
end
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email, :role_id, :user_id)
end
end
And my role model:
class Role < ActiveRecord::Base
has_and_belongs_to_many :users, :join_table => :users_roles
belongs_to :resource, :polymorphic => true
scopify
end
And my user model:
class User < ActiveRecord::Base
rolify
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
As you can see it's pretty much the standard model as generated by Devise.
And here's the form I'm using to update the role:
<div id="role-options-<%= user.id %>" class="reveal-modal medium" style="display: none;">
<%= simple_form_for user, url: user_path(user), html: {method: :put, class: 'custom' } do |f| %>
<h3>Change Role</h3>
<%= f.input :role_ids, collection: Role.all, as: :radio_buttons, label_method: lambda {|t| t.name.titleize}, label: false, item_wrapper_class: 'inline', checked: user.role_ids.first %>
<%= f.submit "Change Role", class: "small button" %>
<a class="close-reveal-modal" href="#">Close</a>
<% end %>
</div>
When I check the new role on the form and submit it, I am redirected to the users page with the message "User updated." However, the user role has not been updated.
I'm still fairly new to Rails and just can't figure out exactly what I am doing wrong. If I understand correctly, I need to update the data in the user_roles table. I just can't figure out what I'm doing wrong.
You are using string params, but forgot to add role_ids into allowed fields.
So, your controller should contain something like this (in case role_ids is an array):
def user_params
params.require(:user).permit(:name, :email, :role_ids => [])
end
Or if role_ids is scalar, just drop => [] part.
More info could be found here
I am not sure what rolify does. But I would do this:
class User
has_one :users_roles
has_one :role, through: :users_roles
I am not sure about this though. But you could give it a try. I know has_one :users_roles is weird.

Resources