NoMethodError- Cant figure out - ruby-on-rails

I am working on a pinterest clone and I am having some trouble when i try to create a new pin. I get "NoMethodError - undefined method pins' for nil:NilClass: app/controllers/api/pins_controller.rb:19:in create'"
I am not sure what else to try. I dont know why it doesnt have access to pins. Any suggestions???
routes.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root to: 'static_pages#root'
namespace :api, defaults: { format: :json } do
resources :users, only: [:show,:new, :create, :index]
resource :session, only: [:new, :create, :destroy, :show]
resources :pins, only: [:create, :show, :index, :edit, :destroy]
resources :boards, only: [:create, :show, :edit, :destroy]
end
end
user.rb
class User < ApplicationRecord
attr_reader :password
validates :username, presence: true, uniqueness: true
validates :password_digest, :session_token, presence: true
validates :password, length: { minimum: 6 }, allow_nil: true
after_initialize :ensure_session_token
has_many :pins,
foreign_key: :author_id,
class_name: :Pin
has_many :boards,
foreign_key: :author_id,
class_name: :Board
has_many :pins_in_boards,
through: :boards,
source: :boards_pins
def self.find_by_credentials(username, password)
user = User.find_by(username: username)
return nil unless user
user.is_password?(password) ? user : nil
end
def password=(password)
#password = password
self.password_digest = BCrypt::Password.create(password)
end
def is_password?(password)
BCrypt::Password.new(self.password_digest).is_password?(password)
end
def ensure_session_token
self.session_token ||= SecureRandom.urlsafe_base64
end
def reset_session_token!
self.session_token = SecureRandom.urlsafe_base64
self.save
self.session_token
end
end
users_controller.rb
class Api::UsersController < ApplicationController
def show
#user = User.find_by(username: params[:id])
if #user
render :show
else
render json: #user.errors.full_messages, status: 404
end
end
def new
#user = User.new
render :new
end
def index
#users =User.all
render :index
end
def create
#user = User.new(user_params)
if #user.save
sign_in(#user)
render "api/users/show"
else
render json: #user.errors.full_messages, status: 422
end
end
private
def user_params
params.require(:user).permit(:password, :username)
end
end
pins_controller.rb
class Api::PinsController < ApplicationController
def index
#pins = user.pins
end
def new
#pin = Pin.new(user_id: current_user.id)
render :new
end
def show
#pin = Pin.find(params[:id])
render :show
end
def create
#pin = current_user.pins.new(pin_params)
if #pin.save
render :show
else
render json: #pin.errors.full_messages, status: 422
end
end
def edit
#pin = Pin.find(params[:id])
unless #pin.author_id == current_user.id
render "api/pins/show"
else
render :edit
end
end
def destroy
pin = current_user.pins.find(params[:id])
pin.destroy
end
private
def pin_params
params.require(:pin).permit(
:title,
:description,
:url,
:author_id,
:photo
)
end
def user
#user ||= User.find(params[:user_id])
end
def pin
#pin ||= current_user.pins.find(params[:id])
end
end
pin.rb
class Pin < ApplicationRecord
validates :title, :description, :author_id, presence: true
belongs_to :user
belongs_to :board
has_many :boards
has_one_attached :photo
has_many :users,
through: :boards,
source: :author
end
creat_pin_form_container.jsx
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import PinForm from './pin_form';
import { createPin } from '../../actions/pins_actions';
import { openModalForm, closeModalForm } from '../../actions/modal_form_actions';
const mapStateToProps = state => ({
pin: {
title: '',
description: '',
photoFile: null
},
formType: 'New Pin'
});
const mapDispatchToProps = dispatch => ({
action: pin => dispatch(createPin(pin)),
closeModalForm: () => dispatch(closeModalForm())
});
export default connect(mapStateToProps, mapDispatchToProps)(PinForm);
pin_form.jsx
import React from 'react';
class PinForm extends React.Component {
constructor(props) {
super(props);
this.state = this.props.pin;
this.handleSubmit = this.handleSubmit.bind(this);
this.handleFile = this.handleFile.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const formData = new FormData();
formData.append('pin[title]', this.state.title);
formData.append('pin[description]', this.state.description);
formData.append('pin[url]', this.state.url);
formData.append('pin[photo]', this.state.photoFile);
this.props.action(formData, this.state.id);
}
update(field) {
return e => this.setState({ [field]: e.currentTarget.value });
}
handleFile(e){
this.setState({ photoFile: e.currentTarget.files[0] })
}
render() {
return (
<div className="pin-form-container">
<form onSubmit={this.handleSubmit}>

This is occurring because the value of current_user is currently set to nil. You need to make sure you have a logged in user.

Related

Why i am getting a 422 - Unprocessable Entity Error

I am working on a pinterest clone and I am having some trouble when i try to create a new pin. I get Completed 422 Unprocessable Entity in 3ms (Views: 0.1ms | ActiveRecord: 0.3ms)
I am not sure what else to try. AT first i thought it was my authenticity token and i tried protect_from_forgery unless: -> { request.format.json? } but still doesn't work.
Any suggestions???
routes.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root to: 'static_pages#root'
namespace :api, defaults: { format: :json } do
resources :users, only: [:show,:new, :create, :index]
resource :session, only: [:new, :create, :destroy, :show]
resources :pins, only: [:create, :show, :index, :edit, :destroy]
resources :boards, only: [:create, :show, :edit, :destroy]
end
end
user.rb
class User < ApplicationRecord
attr_reader :password
validates :username, presence: true, uniqueness: true
validates :password_digest, :session_token, presence: true
validates :password, length: { minimum: 6 }, allow_nil: true
after_initialize :ensure_session_token
has_many :pins,
foreign_key: :author_id,
class_name: :Pin
has_many :boards,
foreign_key: :author_id,
class_name: :Board
has_many :pins_in_boards,
through: :boards,
source: :boards_pins
def self.find_by_credentials(username, password)
user = User.find_by(username: username)
return nil unless user
user.is_password?(password) ? user : nil
end
def password=(password)
#password = password
self.password_digest = BCrypt::Password.create(password)
end
def is_password?(password)
BCrypt::Password.new(self.password_digest).is_password?(password)
end
def ensure_session_token
self.session_token ||= SecureRandom.urlsafe_base64
end
def reset_session_token!
self.session_token = SecureRandom.urlsafe_base64
self.save
self.session_token
end
end
users_controller.rb
class Api::UsersController < ApplicationController
def show
#user = User.find_by(username: params[:id])
if #user
render :show
else
render json: #user.errors.full_messages, status: 404
end
end
def new
#user = User.new
render :new
end
def index
#users =User.all
render :index
end
def create
#user = User.new(user_params)
if #user.save
sign_in(#user)
render "api/users/show"
else
render json: #user.errors.full_messages, status: 422
end
end
private
def user_params
params.require(:user).permit(:password, :username)
end
end
pins_controller.rb
class Api::PinsController < ApplicationController
def index
#pins = user.pins
end
def new
#pin = Pin.new(user_id: current_user.id)
render :new
end
def show
#pin = Pin.find(params[:id])
render :show
end
def create
#pin = current_user.pins.new(pin_params)
if #pin.save
render :show
else
render json: #pin.errors.full_messages, status: 422
end
end
def edit
#pin = Pin.find(params[:id])
unless #pin.author_id == current_user.id
render "api/pins/show"
else
render :edit
end
end
def destroy
pin = current_user.pins.find(params[:id])
pin.destroy
end
private
def pin_params
params.require(:pin).permit(
:title,
:description,
:url,
:author_id,
:photo
)
end
def user
#user ||= User.find(params[:user_id])
end
def pin
#pin ||= current_user.pins.find(params[:id])
end
end
pin.rb
class Pin < ApplicationRecord
validates :title, :description, :author_id, presence: true
belongs_to :user
belongs_to :board
has_many :boards
has_one_attached :photo
has_many :users,
through: :boards,
source: :author
end
creat_pin_form_container.jsx
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import PinForm from './pin_form';
import { createPin } from '../../actions/pins_actions';
import { openModalForm, closeModalForm } from '../../actions/modal_form_actions';
const mapStateToProps = state => ({
pin: {
title: '',
description: '',
photoFile: null
},
formType: 'New Pin'
});
const mapDispatchToProps = dispatch => ({
action: pin => dispatch(createPin(pin)),
closeModalForm: () => dispatch(closeModalForm())
});
export default connect(mapStateToProps, mapDispatchToProps)(PinForm);
pin_form.jsx
import React from 'react';
class PinForm extends React.Component {
constructor(props) {
super(props);
this.state = this.props.pin;
this.handleSubmit = this.handleSubmit.bind(this);
this.handleFile = this.handleFile.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const formData = new FormData();
formData.append('pin[title]', this.state.title);
formData.append('pin[description]', this.state.description);
formData.append('pin[url]', this.state.url);
formData.append('pin[photo]', this.state.photoFile);
this.props.action(formData, this.state.id);
}
update(field) {
return e => this.setState({ [field]: e.currentTarget.value });
}
handleFile(e){
this.setState({ photoFile: e.currentTarget.files[0] })
}
render() {
return (
<div className="pin-form-container">
<form onSubmit={this.handleSubmit}>
<div className="create-edit-form-top">
<nav className="pin-form-header">
<div onClick={this.props.closeModalForm} className="close-pin"><img src={window.cancelURL} /></div>
</nav>
</div>
<div className="new-pin"> <h3>{this.props.formType}</h3></div>
<div className="create-edit-form-left">
<label className="photo-upload">
<img src={this.state.photoUrl} />
<input
type="file"
onChange={this.handleFile}
/>
</label>
</div>
<div className="create-edit-form-right">
<label className="create-edit-form-title">
<input
type='text'
value={this.state.title}
placeholder="Add your title"
onChange={this.update('title')}
/>
</label>
<label className="create-edit-form-description">
<textarea
cols="30"
rows="1"
value={this.state.description}
placeholder="Tell everyone what your Pin is about"
onChange={this.update('description')}
/>
</label>
<label className="add-url">
<input
type='text'
placeholder="Add a destination link"
onChange={this.update('url')}
/>
</label>
</div>
<button className="pin-submit" type='submit'>Save</button>
</form>
</div>
);
}
}
export default PinForm;
Use
protect_from_forgery with: :null_session

Limiting a select_tag list to only objects that belong_to another object in rails

I have a list of classrooms that belong_to a school and a school has_many classrooms. I have users who belong to a school and fill out a form of information. On this form I have the following selector:
Pins/_form.html.erb
<div class="form-group">
<%= label_tag(:classroom, "Select your classroom:") %>
<%= select_tag "pin[code]", options_from_collection_for_select(Classroom.all, "code", "code", ) %>
</div>
Right now this form shows all the classrooms listed in the data base. I need it to show just the classrooms that belong to the school. Classrooms have a name and a code, the code is what ties the students form submission to that classroom.
I'm still learning RoR and have struggled to figure this type of problem one out on a couple of occasions.
Here's the Classroom Controller
class ClassroomsController < ApplicationController
before_action :set_classroom, only: [:show, :edit, :update, :destroy]
after_action :verify_authorized
respond_to :html
def home
#classrooms = Classroom.all
respond_with(#classrooms)
authorize #classrooms
end
def index
#classrooms = Classroom.all
respond_with(#classrooms)
authorize #classrooms
end
def show
respond_with(#classroom)
end
def new
#school = School.find(params[:school_id])
#classroom = #school.classrooms.new
#teachers = #school.teachers
respond_with(#classroom)
flash[:notice] = "Classroom created."
authorize #classroom
end
def edit
end
def create
#school = School.find(params[:school_id])
#classroom = #school.classrooms.new(classroom_params)
#classroom.save
respond_with #school
authorize #classroom
end
def update
#classroom.update(classroom_params)
respond_with([#school,#classroom])
end
def destroy
#classroom.destroy
redirect_to #school
flash[:notice] = "You have succesfully deleted the classroom."
end
private
def set_classroom
#classroom = Classroom.find(params[:id])
#school = School.find(params[:school_id])
authorize #classroom
end
def classroom_params
params.require(:classroom).permit(:teacher_id, :name, :code)
end
end
Pins_controller
class PinsController < ApplicationController
before_action :set_pin, only: [:show, :edit, :update, :destroy]
respond_to :html
def show
respond_with(#pin)
end
def new
#pin = Pin.new
#emotions = Emotion.all
#causes = Cause.all
#school = School.find(params[:school])
#classrooms = #school.classrooms
respond_with(#pin)
authorize #pin
end
def edit
end
def create
code = params[:pin][:code]
#classroom = Classroom.where('code LIKE ?', code).first
unless #classroom
flash[:error] = "Classroom code incorrect"
#emotions = Emotion.all
#causes = Cause.all
render :new
else
params[:pin][:classroom_id] = #classroom.id
#pin = Pin.new(pin_params)
#pin.save
params[:pin][:cause_ids].each do |cause_id|
#cause = Cause.find(cause_id)
#pin.causes << #cause
end
params[:pin][:emotion_ids].each do |emotion_id|
#emotion = Emotion.find(emotion_id)
#pin.emotions << #emotion
end
if #pin.save
redirect_to signout_path and return
end
respond_with(#pin)
authorize #pin
end
end
def update
#pin.update(pin_params)
respond_with(#pin)
authorize #pin
end
def destroy
#pin.destroy
respond_with(#pin)
authorize #pin
end
private
def set_pin
#pin = Pin.find(params[:id])
authorize #pin
end
def pin_params
params.require(:pin).permit(:user_id, :question, :question1, :question2,
:question3, :question4, :question5, :classroom_id, :sad,
:happy, :mad, :brave, :embarrassed, :sorry, :frustrated,
:silly, :left_out, :excited, :hurt, :jealous, :confused,
:proud, :other)
end
end
School.rb model
class School < ActiveRecord::Base
has_many :users
has_many :classrooms
validates_uniqueness_of :code
def classrooms
self.users.classrooms
end
def students
self.users.students
end
def teachers
self.users.teachers
end
def admins
self.users.admins
end
end
User Model
class User < ActiveRecord::Base
devise :timeoutable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :pins
has_many :reflections
has_many :classrooms, :foreign_key => :teacher_id
belongs_to :school
validates :name, presence: true
validates :role, presence: true
# validates :school, presence: true
scope :students, -> { where(role: "student") }
scope :teachers, -> { where(role: "teacher")}
scope :teachers_and_admins, -> { where(:role => ["teacher", "admin"]) }
scope :admins, -> { where(role: "admin" ) }
scope :online, lambda{ where("updated_at > ?", 15.days.ago) }
def online?
updated_at > 15.days.ago
end
def admin?
role == "admin"
end
def teacher?
role == "teacher"
end
def student?
role == "user" || role == "student"
end
def superadmin?
role == "superadmin"
end
def admin_of_school?(school)
self.admin? && self.school == school
end
def teacher_of_school?(school)
self.teacher? && self.school == school
end
def admin_or_teacher_of_school?(school)
self.admin_of_school?(school) || self.teacher_of_school?(school)
end
end
classroom model
class Classroom < ActiveRecord::Base
belongs_to :school
belongs_to :teacher, :class_name => "User"
has_and_belongs_to_many :users
has_many :pins
has_many :reflections
validates_presence_of :school
validates_presence_of :teacher
validates :code, :uniqueness => { :scope => :school_id }
end
I found a similar answer here: Rails only give records that "belong_to"
But it didn't help me understand how to limit the drop down list to only Classrooms of the current school.
Any ideas on how to handle his situation?
You already select the school in the controller, so just use it in the view, instead of doing a Classroom.all do a #school.classrooms
<%= select_tag "pin[code]",
options_from_collection_for_select(#school.classrooms, "code", "code")
%>
This part isn't an answer, but improvements and fixes to your code
First the User model can stay as it is
class User < ActiveRecord::Base
#devise place holder
# assocciations
has_many :pins
has_many :reflections
has_many :classrooms, foreign_key: :teacher_id
belongs_to :school
#validations place holder
#scopes
scope :students, -> { where(role: "student") }
scope :teachers, -> { where(role: "teacher")}
scope :admins, -> { where(role: "admin" ) }
scope :teachers_and_admins, -> { teachers.admins }
scope :online, -> { where("updated_at > ?", 15.days.ago) }
# some check methods
end
classroom class
class Classroom < ActiveRecord::Base
belongs_to :school
belongs_to :teacher, ->{ User.teachers }, class_name: 'User'
has_many :pins
has_many :reflections
end
school class
class School < ActiveRecord::Base
has_many :users
has_many :admins, ->{ User.admins }, class: User
has_many :students, ->{ User.students }, class: User
has_many :teachers, ->{ User.teachers }, class: User
has_many :classrooms
end
Now the controllers
You need to clean up the duplications, so here's an example from ur pins#new action
def new
#pin = Pin.new
prepare_lookups
respond_with(#pin)
authorize #pin
end
def prepare_lookups
#emotions = Emotion.all
#causes = Cause.all
#school = School.find(params[:school])
#classrooms = #school.classrooms
end
I removed the common code to a separate method, and call it whenever i need, of course you can add or remove from that method according to your needs.
Anyways, I think you should read more about active record assocciations and the conventions in writing controller actions

Multi-select validation always fail

I have few multi-selects in my app that validation always fail (getting form errors: genres can't be blank, languages can't be blank) during every form submit (even if the multi-select options were selected). Code:
models/dvd.rb
class Dvd < ActiveRecord::Base
has_and_belongs_to_many :genres
has_and_belongs_to_many :languages
has_many :rentals, dependent: :destroy
has_many :users, through: :rentals
validates :title, presence: true
validates :year, inclusion: {in: 1900..Time.now.year.to_i}, :presence => {:message => 'Year must be from 1900 till current year.'}
validates :length, inclusion: {in: 1..999}, :presence => {:message => 'DVD length must be in minutes in range 1..999.'}
validates :genres, presence: true
validates :languages, presence: true
end
models/language.rb
class Language < ActiveRecord::Base
has_and_belongs_to_many :dvds
validates :title, presence: true, uniqueness: { case_sensitive: false }
end
models/genre.rb
class Genre < ActiveRecord::Base
has_and_belongs_to_many :dvds
validates :title, presence: true, uniqueness: { case_sensitive: false }
end
dvds_controller.rb
class DvdsController < ApplicationController
before_action :set_dvd, only: [:show, :edit, :update, :destroy]
before_action :set_genres, :set_languages, only: [:new, :edit]
before_action :delete_genres, :delete_languages, only: [:update]
after_action :add_genres, :add_languages, only: [:create, :update]
# GET /dvds
# GET /dvds.json
def index
#dvds = Dvd.all
end
# GET /dvds/1
# GET /dvds/1.json
def show
end
# GET /dvds/new
def new
#dvd = Dvd.new
end
# GET /dvds/1/edit
def edit
end
# POST /dvds
# POST /dvds.json
def create
#dvd = Dvd.new(dvd_params)
respond_to do |format|
if #dvd.save
format.html { redirect_to #dvd, notice: 'Dvd was successfully created.' }
format.json { render :show, status: :created, location: #dvd }
else
format.html { render :new }
format.json { render json: #dvd.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /dvds/1
# PATCH/PUT /dvds/1.json
def update
respond_to do |format|
if #dvd.update(dvd_params)
format.html { redirect_to #dvd, notice: 'Dvd was successfully updated.' }
format.json { render :show, status: :ok, location: #dvd }
else
format.html { render :edit }
format.json { render json: #dvd.errors, status: :unprocessable_entity }
end
end
end
# DELETE /dvds/1
# DELETE /dvds/1.json
def destroy
#dvd.destroy
respond_to do |format|
format.html { redirect_to dvds_url, notice: 'Dvd was successfully deleted.' }
format.json { head :no_content }
end
end
private
def set_dvd
if params[:id]
#dvd = Dvd.find(params[:id])
else
#dvd = Dvd.find(params[:dvd][:id])
end
end
def dvd_params
params.require(:dvd).permit(:title, :description, :year, :genres, :languages, :length)
end
def add_languages
params[:dvd][:languages].each do |l|
if !l.empty?
#dvd.languages << Language.find(l)
end
end
end
def add_genres
params[:dvd][:genres].each do |g|
if !g.empty?
#dvd.genres << Genre.find(g)
end
end
end
def set_genres
#genres = Genre.all
end
def set_languages
#languages = Language.all
end
def delete_genres
# Delete all dvd genre relations
#dvd.genres.delete_all
end
def delete_languages
# Delete all dvd language relations
#dvd.languages.delete_all
end
end
routes.rb
Rails.application.routes.draw do
resources :dvds do
resources :rentals
end
resources :rentals
resources :languages
resources :genres
resources :dvds
resources :users, :path => 'clients'
root to: "index#index"
end
form
<div class="field">
<%= f.label :genres %><br>
<%= f.collection_select(:genres, Genre.all, :id, :title, {:selected => #dvd.genres.map {|dl| dl.id}, :include_blank => false}, {:multiple => true}) %>
</div>
<div class="field">
<%= f.label :languages %><br>
<%= f.select :languages, options_for_select(Language.all.map {|l| [l.title,l.id]}, #dvd.languages.map {|dl| dl.id}), {:include_blank=> false}, {:multiple => true} %>
</div>
Any ideas what is wrong with that?
The field names for the form should be genre_ids and language_ids, not genres and languages.

uninitialized constant User::CompaniesRate

I am newbie in rails. I am trying to generate a page form. but I am geting this error.
I could not understand where is my problem.
this was the error showing and it was highlighting in this line
#companies_rates =#user.companies_rates
Here I will be having userpage, companies_rate and page3 where each pages have user id and companies rate has an column same column also exit in the page 3. Now i want display companies_rate and page 3 seperately
NameError in UsersController#show
uninitialized constant User::CompaniesRate
#user = User.find(params[:id])
#companies_mines= #user.companies_mines
**#companies_rates =#user.companies_rates**
#title=#user.name
end
Here is my users controller
class UsersController < ApplicationController
before_action :signed_in_user,
only: [:index, :edit, :update, :destroy, :following, :followers]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
#users = User.paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
#companies_mines= #user.companies_mines
#companies_rates =#user.companies_rates
#title=#user.name
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
sign_in #user
flash[:success] = "Welcome to skillable"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
And here is my companies_rate controller
class CompaniesRatesController < ApplicationController
before_action :signed_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def index
#companies_rates = companies_rates.all
end
def show
#companies_rates = companies_rate.find(params[:id])
end
def new
#companies_rates = companies_rates.new
end
def create
#companies_rates = companies_rates .new(params[:company,:r1,:r2,:r3])
if #post.save
redirect_to companies_rates _path, :notice => "Your post was saved"
else
render "new"
end
end
def edit
end
def update
end
def destroy
end
private
def companies_rates_params
params.require(:companies_rates).permit(:company, :r1, :r2, :r3 )
end
def correct_user
#companies_rates = current_user.companies_rates.find_by(id: params[:id])
redirect_to root_url if #ompanies_rates.nil?
end
end
Here is my users modal
class User < ActiveRecord::Base
attr_accessor :password
#attr_accessible :name, :email, :password, :password_confirmation
has_many :companies_mines
has_many :companies_rates
before_save { self.email = email.downcase }
before_create :create_remember_token
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.encrypt(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.encrypt(User.new_remember_token)
end
end
Here is my companies_rates
class CompaniesRates < ActiveRecord::Base
#attr_accessible :company, :r1, :r2, :r3
belongs_to :user
validates :company, presence: true, length: { maximum: 140 }
validates :user_id, presence: true
belongs_to :user
default_scope :order => 'companies_rates.created_at DESC'
end
Can any on tell what is my problem and how to solve it.
Change the model name to CompaniesRate.Model name should be singular

User returning nil. undefined method `username' for nil:NilClass

Here is the error I receive:
Here is a Gist of the files (some of you may find this easier to read):
https://gist.github.com/drichards2013/7902811
Here is index.html.erb:
<%= render 'pages/home' if !user_signed_in? %>
<div id="things" class="transitions-enabled">
<% #things.each do |thing| %>
<div class='panel panel default'>
<div class="box">
<%= link_to image_tag(thing.image.url(:medium)), thing %>
<div class='panel-body'>
<% if thing.link.blank? %>
<strong><%= thing.title %></strong>
<% else %>
<strong><%= link_to thing.title, "http://#{thing.link}"%></strong>
<% end %>
<p><%= thing.description %></p>
By <%= link_to thing.user.username, user_path(thing.user) %>
<% if thing.user == current_user %>
<%= link_to edit_thing_path(thing) do %>
<span class='glyphicon glyphicon-edit'></span>
<% end %>
<%= link_to thing_path(thing), method: :delete, data: { confirm: 'Are you sure?' } do %>
<span class='glyphicon glyphicon-trash'></span>
<% end %>
</div>
<% end %>
</div>
</div>
<% end %>
</div>
<%= will_paginate #posts, renderer: BootstrapPagination::Rails, class: 'pull-left' %>
Here is thing.rb:
class Thing < ActiveRecord::Base
belongs_to :user
default_scope -> { order('created_at DESC') }
has_attached_file :image, :styles => { :large => '500x500>', :medium => '300x300>', :thumb => '100x100>' }
validates :image, presence: true
validates :title, presence: true, length: { minimum: 5, maximum: 50 }
# Returns microposts from the users being followed by the given user.
def self.from_users_followed_by(user)
followed_user_ids = "SELECT followed_id FROM relationships
WHERE follower_id = :user_id"
where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
user_id: user.id)
end
end
class ThingsController < ApplicationController
before_action :set_thing, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
# GET /things
# GET /things.json
def index
#things = Thing.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 50)
end
# GET /things/1
# GET /things/1.json
def show
end
# GET /things/new
def new
#thing = current_user.things.build
end
# GET /things/1/edit
def edit
end
# POST /things
# POST /things.json
def create
#thing = current_user.things.build(thing_params)
respond_to do |format|
if #thing.save
format.html { redirect_to #thing, notice: 'Thing was successfully created.' }
format.json { render action: 'show', status: :created, location: #thing }
else
format.html { render action: 'new' }
format.json { render json: #thing.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /things/1
# PATCH/PUT /things/1.json
def update
respond_to do |format|
if #thing.update(thing_params)
format.html { redirect_to #thing, notice: 'Thing was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #thing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /things/1
# DELETE /things/1.json
def destroy
#thing.destroy
respond_to do |format|
format.html { redirect_to things_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_thing
#thing = Thing.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def thing_params
params.require(:thing).permit(:title, :description, :image, :link)
end
end
Here is things_controller.rb:
class ThingsController < ApplicationController
before_action :set_thing, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
# GET /things
# GET /things.json
def index
#things = Thing.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 50)
end
# GET /things/1
# GET /things/1.json
def show
end
# GET /things/new
def new
#thing = current_user.things.build
end
# GET /things/1/edit
def edit
end
# POST /things
# POST /things.json
def create
#thing = current_user.things.build(thing_params)
respond_to do |format|
if #thing.save
format.html { redirect_to #thing, notice: 'Thing was successfully created.' }
format.json { render action: 'show', status: :created, location: #thing }
else
format.html { render action: 'new' }
format.json { render json: #thing.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /things/1
# PATCH/PUT /things/1.json
def update
respond_to do |format|
if #thing.update(thing_params)
format.html { redirect_to #thing, notice: 'Thing was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #thing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /things/1
# DELETE /things/1.json
def destroy
#thing.destroy
respond_to do |format|
format.html { redirect_to things_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_thing
#thing = Thing.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def thing_params
params.require(:thing).permit(:title, :description, :image, :link)
end
end
Here is 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 :things
validates :name, presence: true, length: { minimum: 2, maximum: 20}
validates :username, presence: true, length: { minimum: 2, maximum: 20}
validates :username, uniqueness: true
validates :email, presence: true
validates :email, uniqueness: true
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" , :nav => "25x25"}
extend FriendlyId
friendly_id :username
def show
end
#follow features
has_many :followed_users, through: :relationships, source: :followed
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :followed_users, through: :relationships, source: :followed
def following?(other_user)
relationships.find_by(followed_id: other_user.id)
end
def follow!(other_user)
relationships.create!(followed_id: other_user.id)
end
def unfollow!(other_user)
relationships.find_by(followed_id: other_user.id).destroy!
end
def feed
Thing.from_users_followed_by(self)
end
has_many :reverse_relationships, foreign_key: "followed_id",
class_name: "Relationship",
dependent: :destroy
has_many :followers, through: :reverse_relationships, source: :follower
end
Here is users_controller.rb:
class UsersController < ApplicationController
def show
#user = User.find_by_username(params[:id])
end
def user_params
params.require(:user).permit(:avatar)
end
def following
#title = "Following"
#user = User.find_by_username(params[:id])
#users = #user.followed_users.paginate(page: params[:page])
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.find_by_username(params[:id])
#users = #user.followers.paginate(page: params[:page])
render 'show_follow'
end
end
What I have tried
I went to the console, did thing = Thing.last, then tried to call thing.user, and that returned nil. So it appears the user_id isn't saving. How can I make that happen?
This is where the "try" method is your friend.
You're trying to get the "username" value from your user, which is missing.
If you were to write your line like:
thing.user.try(:username)
Then it would not crash, and it would fetch the username if user existed.
Your user is not saving because your one-to-many relationship is not set up. You might want to add a user_id to your things table.
Fixed by adding :user_id to the thing_params method in my things controller.
def thing_params
params.require(:thing).permit(:title, :description, :image, :link, :user_id)
end

Resources