Undefined method error with has_one association - ruby-on-rails

I have a Shop model and a User model. Logic is that users can have one shop and shops can have one users associated with them, so I am using the has_one: shop association.
But while creating a new shop for a new user am getting this error
undefined method 'shops' for #<\User:0x007f6f30659068> Did you mean? shop shop=
I don't understand what's gone wrong. I am sure I must have done something stupid, here's my code:
class ShopsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
def new
#shop = current_user.shop.build
end
def create
#shop = current_user.shops.build(shop_params)
#shop.user = current_user
respond_to do |format|
if #shop.save
format.html { redirect_to #shop, notice: 'Shop was successfully created.' }
format.json { render :show, status: :created, location: #shop }
else
format.html { render :new }
format.json { render json: #shop.errors, status: :unprocessable_entity }
end
end
end
private
def shop_params
params.require(:shop).permit(:name, :description, :imageshop, :location, :web, :email, :phone, :business_type, :category)
end
end
class Shop < ApplicationRecord
mount_uploader :imageshop, ImageUploader
belongs_to :user
end
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :products, dependent: :destroy
has_one :shop
end

I think you need to change
#shop = current_user.shops.build(post_params)
to
#shop = current_user.build_shop(post_params)
This is because you have specified that a User can have one Shop.
Hope it helps!

Related

Rails Beginner NoMethodError in PinsController#new

having issues keep getting error undefined method `pins' for nil:NilClass, can someone explain how to fix this error. Been following a tutorial and recently got stuck.
pins_controller.rb
class PinsController < ApplicationController
before_action :find_pin, only: [:show, :edit, :update, :destroy]
def index
#pins = Pin.all.order("created_at DESC")
end
def new
#pin = current_user.pins.build
end
def create
#pin = current_user.pins.build(pin_params)
if #pin.save
redirect_to #pin, notice: "Successfully created new Pin"
else
render 'new'
end
end
def edit
end
def update
if #pin.update(pin_params)
redirect_to #pin, notice: "Pin was Successfully updated!"
else
render 'edit'
end
end
def destroy
#pin.destroy
redirect_to root_path
end
private
def pin_params
params.require(:pin).permit(:title, :description)
end
def find_pin
#pin = Pin.find(params[:id])
end
end
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_many :pins
end
pin.rb
class Pin < ActiveRecord::Base
belongs_to :user
end
routes.rb
Rails.application.routes.draw do
devise_for :users
resources :pins
root "pins#index"
end
If you are using the gem Devise then the helper method current_user returns you the current logged in user in your session.
Pleases make sure a user is logged in/
You can make sure that the user is logged in by adding before_action :authenitcate_user! in your application controller(for all actions in your application).
If you are using devise, you might want to add
before_action :authenitcate_user!
method inside pins controller which ensures that the user is logged in.

Devise Validations with Associations

I have a User model generated using Devise. This User model has 2 types (Buyer or Seller) created using Polymorphic Associations.
class Buyer < ActiveRecord::Base
has_one :user, as: :owner, dependent: :destroy
accepts_nested_attributes_for :user
validates_presence_of :user
validates_associated :user
class User < ActiveRecord::Base
after_commit :transaction_success
after_rollback :transaction_failed
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :owner, polymorphic: true
validates :email, presence: true
validates :first_name, presence: true
private
def transaction_success
logger.info "Transfer succeed for Account #{self.to_param}"
end
def transaction_failed
logger.warn "Transfer failed for Account #{self.to_param}"
end
end
When an User is Registered, he does it from an specific registration link (/buyer/new or /seller/new), calling the create method from the controller:
def create
#buyer = Buyer.new(buyer_params)
#user = User.new(user_params)
respond_to do |format|
begin
User.transaction do
#buyer.save
#user.owner_id = #buyer.id
#user.owner_type = "Buyer"
#user.save
end
format.html { sign_in_and_redirect #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
rescue ActiveRecord::Rollback
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
The problem is that sometimes the transaction fails but saves a Buyer without an User. Also, the Devise validations, or any validation that I include in the User Model doesn't make any difference, allowing users to be created without any email, password etc.
How can I fix the transaction and make sure that the validations work??

Devise: NameError (undefined local variable or method `user_id=') in controller when using `current_user`

I'm using Devise in my Rails app. A Project belongs to a (devise) User. (Relevant models are below.)
When the create action is called in ProjectsController, however, the following error is shown in the server logs:
NameError (undefined local variable or method `user_id=' for #<Project:0x007f4c1a0aa3a8>):
app/controllers/projects_controller.rb:20:in `create'
Any ideas?
Project.rb
class Project < ActiveRecord::Base
belongs_to :user
has_many :timestamps
end
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_many :projects
end
projects_controller.rb (relevant parts)
class ProjectsController < ApplicationController
before_action :authenticate_user!
def create
#project = current_user.projects.new(project_params)
respond_to do |format|
if #project.save
format.html { redirect_to #project, notice: 'Project was successfully created.' }
format.json { render :show, status: :created, location: #project }
else
format.html { render :new }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
devise_for :users
resources :projects do
resources :timestamps
end
end
It's the #project = current_user line that's causing the problem. Looks like it isn't recognising the method, which is weird.
Thanks for the help :)
Just in case anyone else makes the same mistake and doesn't think to check their db schema, here's what was causing the problem.
I'd forgotten to add a foreign key (user_id) to the projects table, even though I'd added the belongs_to association in the model.
To fix the problem, I ran the following migration:
class AddUserToProjects < ActiveRecord::Migration
def change
add_reference(:projects, :user, foreign_key: true, index: true)
end
end
and then of course ran rake db:migrate

How to set dependence between models in RubyOnRails

I have two models: User and Sensor. I want to set dependence has_many and belongs_to.
Sensor model
class Sensor < ActiveRecord::Base
attr_accessible :user_id, :data, :ids, :voltage, :status
belongs_to :user
end
and User model
class User < ActiveRecord::Base
has_many :sensors
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
In the new migration i created new column
class AddUserId < ActiveRecord::Migration
def change
add_column :sensors, :user_id, :integer
end
end
And Create method in the Sensor Controller
def create
#sensor = Sensor.new(sensor_params)
respond_to do |format|
if #sensor.save
format.html { redirect_to #sensor, notice: 'Sensor was successfully created.' }
format.json { render action: 'show', status: :created, location: #sensor }
else
format.html { render action: 'new' }
format.json { render json: #sensor.errors, status: :unprocessable_entity }
end
end
end
And when i press the create button,the dependence doesn't set
I guess you have current_user in your application.
SO in the create action, please try the following code.
def create
#sensor = current_user.sensors.new(sensor_params)
# YOUR CODE GOES HERE
end

overriding Devises "You are already signed in" by signing the user out, redirecting to authentication page

How do I change from showing this message to logging the user out and redirecting him to an authentication page? From other threads on the subject, I understood that the Devise SessionsController has to be altered, but I don't understand how to apply those examples to mine and where is this controller even located?
I'm working on an app where I have a User model and a Page model, like on Facebook. Both of these models have Devise added to them. When I'm signed in under a User account and try to create the page, I get the "You are already signed in" message and the log shows Filter chain halted as :require_no_authentication rendered or redirected. When a signed in user tries to create a page, what I want to happen is to get redirected to the page, where this user can either log back in and by doing so confirm that he wants this page under his account, or create a whole new account under different email that will only manage this new page.
create method for pages
class PagesController < ApplicationController
before_action :set_page, only: [:show, :edit, :update, :destroy]
def index
#pages = Page.all
end
def show
end
def new
#page = Page.new
end
def edit
end
def create
#page = Page.new(page_params)
respond_to do |format|
if #page.save
format.html { redirect_to #page, notice: 'Page was successfully created.'
}
format.json { render action: 'show', status: :created, location: #page }
else
format.html { render action: 'new' }
format.json { render json: #page.errors, status: :unprocessable_entity }
end
end
end
page model
class Page < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :likes
has_many :users, :through => :likes
has_many :events
end
user model
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :likes
has_many :pages, :through => :likes
end

Resources