Error: undefined method `[]' for nil:Class - ruby-on-rails

The error says that there is an: "undefined method []"
My questions is simply how to solve the error
My user.rb file where the error says the error is and where i think the error is
def your_questions(params)
questions.paginate(page: params[:page], order: 'created_at DESC', per_page: 3)
end
My questions controller a.k.a app/controllers/questions_controller.rb
class QuestionsController < ApplicationController
before_filter :auth, only: [:create, :your_questions, :edit, :update]
# def index
# #question = Question.new
# #questions = Question.unsolved(params)
# end
def self.unsolved(params)
order('created_at DESC').where(solved: false).paginate(page: params[:page],per_page: 3)
end
def create
#question = current_user.questions.build(params[:question])
if #question.save
flash[:success] = 'Your question has been posted!'
redirect_to #question
else
#questions = Question.unsolved(params)
render 'index'
end
end
def new
#question = Question.new
end
def show
# raise FOO
puts params
#question = Question.find(params[:id])
#answer = Answer.new
end
def your_questions
#questions = current_user.your_questions(params[:id])
end
def edit
#question = current_user.questions.find(params[:id])
end
def update
#question = current_user.questions.find(params[:id])
if #question.update_attributes(params[:question])
flash[:success] = 'Your question has been updated!'
redirect_to #question
else
render 'edit'
end
end
def search
#questions = Question.search(params)
end
end

You pass params[:id] into your_questions method, while it expects params. What I'd do is:
def your_questions(page)
questions.paginate(page: page, order: 'created_at DESC', per_page: 3)
end
It's because this method doesn't need to know about your whole params hash. Then you call this method simply with params[:page]:
current_user.your_questions(params[:page])

Your are passing only id when you have called your_questions in your controller. However you are trying to fetch a key :page from id (string)
Just Do following change in your controller's your_questions
#questions = current_user.your_questions(params[:page])
In your user.rb just use page instead of params[:page]
def your_questions(page)
questions.paginate(page: page, order: 'created_at DESC', per_page: 3)
end

Related

why does my routes give me wrong direction

I'm having a association between user, store and item like this:
user has one store
store has many items
item belongs to store
So when I create item it must belongs to the current user's store
Now, I logged in as user_1 , I want to search for user_2's item. But if I didn't create user_1's store, It keep redirecting me to localhost:3000/stores
in items_controller.rb:
class ItemsController < ApplicationController
before_action :find_item, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, only: [:new, :edit]
def index
if params[:category].blank?
#items = Item.all.order("created_at DESC")
end
if params[:category]
#category_id = Category.find_by(name: params[:category]).id
#items = Item.where(category_id: #category_id).order("created_at DESC")
end
end
def show
end
def new
#store = current_user.store
#item = #store.items.build
#categories = Category.all.map{ |c| [c.name, c.id] }
end
def update
#item.category_id = params[:category_id]
if #item.update(item_params)
redirect_to item_path(#item)
else
render 'edit'
end
end
def create
#store = current_user.store
#item = #store.items.build(item_params)
#item.category_id = params[:category_id]
if #item.save
flash[:success] = "Creating item success"
redirect_to #item
else
render 'new'
end
end
private
def item_params
params.require(:item).permit(:code, :name, :description, :producer, :item_img, :store_id,
:category_id )
end
def find_item
#item = Item.find(params[:id])
end
def find_user
#user = User.find_by(params[:user_id])
end
end
in stores_controller.rb:
class StoresController < ApplicationController
before_action :find_store, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
before_action :find_user
def show
if current_user.store.blank?
redirect_to new
else
#items = Item.where(store_id: #store.id)
end
end
def index
#stores = Store.all.order("created at DESC")
end
def new
#store = current_user.build_store
end
def create
#store = current_user.build_store(store_params)
if #store.save
session[:store_id] = #store.id
flash[:success] = "Creating item success"
redirect_to #store, notice: 'success'
else
render 'new'
end
end
private
def store_params
params.require(:store).permit( :name , :user_id)
end
def find_store
#store = Store.find(params[:id])
end
def find_user
#user = Store.find_by(params[:user_id])
end
end
The error raised whenever I click on the button in items/show.html.erb.
In items/show.html.erb:
<button>see more item from:<%= link_to #item.store.name, store_path(#item.store.id)%></button>
in routes.rb:
devise_for :users
resources :items
resources :stores
In the show method for stores_controller, I still want to load the current_user's store in navbar section to make sure he can add more items to his store when he logged in.
I'm still a newbie in rails and I'm looking for solutions to solve this problem :-)
If a store requires a user_id then you don't need before_action :find_user because you can get the store's user just by calling store.user
It looks like you require the current_user to have a store but what if they are not logged in? Shouldn't it be this?
def show
if current_user && current_user.store.blank?
redirect_to new
else
#items = Item.where(store_id: #store.id)
end
end

Rails throwing error instead validating

I am building a fairly straightforward Rails 5 application. You create "Movies," and then can create "Reviews" for those movies. Rails is doing something odd. I have my application set up so instead of a "new" action and a corresponding view, I have the form to create new movies in a modal contained in the application.html.erb file. I then provide #newmovie = Movie.new in the controller for all the movie views, so the data is available everywhere.
I have validations for the movie object setup like this:
class Movie < ApplicationRecord
has_many :reviews
validates :title, :director, :poster, :synopsis, presence: true
end
When I fill out the form to create a new movie in the modal on my index view and intentionally leave fields blank (to trigger the validation), I get this:
instead of the form simply not accepting the input. What's going on here? I can't have this error happening like this. Previously, I had a "new" view. This did not happen in the previous setup. Help!
Here is my entire movies controller:
class MoviesController < ApplicationController
before_action :find_movie, only: [:show, :edit, :update, :destroy ]
before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
before_action :find_newmovie, only: [:show, :index, :new, :edit]
def show
#reviews = #movie.reviews.all.order(created_at: :desc).paginate(:page => params[:page], :per_page => 3)
#review = Review.new
if #movie.reviews.blank?
#average_review = 0
else
#average_review = #movie.reviews.average(:rating).round(2)
end
end
def index
#movies = Movie.all.order(title: :asc).paginate(:page => params[:page], :per_page => 3)
#newmovie = Movie.new
end
def new
#movie = Movie.new
end
def create
#movie = Movie.create(movie_params)
#movie.user_id = current_user.id
if #movie.save
flash[:success] = "Your movie was created!"
redirect_to root_path
else
flash[:danger] = "There was a problem with your request"
render :new
end
end
def edit
end
def update
if #movie.update(movie_params)
flash[:success] = "Your movie was updated"
redirect_to movie_path
else
flash[:danger] = "There was a problem with your request"
end
end
def destroy
if #movie.destroy
flash[:success] = "Your movie was removed"
redirect_to movies_path
else
flash[:danger] = "There was a problem with your request"
render :index
end
end
private
def movie_params
params.require(:movie).permit(:title, :director, :poster, :synopsis, :user_id)
end
def find_movie
#movie = Movie.find(params[:id])
end
def find_newmovie
#newmovie = Movie.new
end
end
In new action of movies_controller, you missed to initalize the instance variable #newmovie.
add below code in movies_controller:
class MoviesController < ApplicationController
def new
#newmovie = Movie.new
end
...
end

The action 'destroy' could not be found for MessagesController 1

I keep getting the error destroy action can not be found in the messagesController. But i have the destroy action setup i don't get why i am getting this message error. Can some one tell me why i can getting this error?
class MessagesController < ApplicationController
before_action :find_message, only: [:show, :edit, :update, :destroy]
def index
#messages = Message.all.order("created_at DESC")
end
def show
end
def new
#message = Message.new
end
def create
#message = Message.new(message_params)
if #message.save
redirect_to root_path
else
render 'new'
end
def edit
end
def update
if #message.update(message_params)
redirect_to message_path
else
render 'edit'
end
end
def destroy
#message.destroy
redirect_to root_path
end
end
private
def message_params
params.require(:message).permit(:title, :description)
end
def find_message
#message = Message.find(params[:id])
end
end
You missed an end closure for your create action. The right way should be this:
def create
#message = Message.new(message_params)
if #message.save
redirect_to root_path
else
render 'new'
end
end
def edit
end
Your create action is missing an end statement:
def create
#message = Message.new(message_params)
if #message.save
redirect_to root_path
else
render 'new'
end
# This is defined before create is closed
def edit
end

Rails: param is missing or the value is empty. strong parameters in controller

i have this controller
class StoresController < ApplicationController
before_filter :authenticate_business!, :except => [:index, :show]
def index
##stores = Store.paginate(:page => params[:page])#, :per_page => 8)
if params[:query].present?
#stores = Store.search(params[:query], page: params[:page])
else
#stores = Store.all.page params[:page]
end
end
def show
#store = Store.friendly.find(params[:id])
if request.path != store_path(#store)
redirect_to #store, status: :moved_permanently
end
end
def new
#store = Store.new
end
def create
#store = Store.new(store_params)
#store.business_id = current_business.id
if #store.save
redirect_to #store
else
render 'new'
end
end
def edit
#store = Store.friendly.find(params[:id])
end
def update
#store = Store.friendly.find(params[:id])
if #store.update(store_params)
redirect_to #store
else
render 'edit'
end
end
def destroy
#store = Store.friendly.find(params[:id])
#store.destroy
redirect_to stores_url
end
private
def store_params
params.require(:store).permit(:name, :description, :address, :telephone, :email, :website)
end
end
and a view with a form to create a new store.
<%= form_for #store do |f| %>
.......
code
......
<% end %>
The problem is that when i submit the form, it gives me this error "param is missing or the value is empty: store", pointing at line "params.require(:store).permit(:name, :description, :address, :telephone, :email, :website)"
Any idea to solve this problem?
Thank you.
I had this same issue and it was caused by a route issue, as discussed in the comments, causing the form not to post any data.
I think what you need is to make sure 'get' requests to the 'new' route access your 'new' method, while 'post' requests to the 'new' route access your 'create' method. Something like:
get 'stores/new' => 'stores#new'
post 'stores/new' => 'stores#create'

Best way to avoid duplication of related objects in the actions new and create

To create an user in the example bellow I have to load #projects and #companies as they are mandatory for creating user.
class UsersController < ApplicationController
def new
#user = User.new
# duplication here
#projects = Project.all
#companies = Company.all
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
# and here
#projects = Project.all
#companies = Company.all
render :action => "new"
end
end
end
I have to load these dependencies in both (duplication) cases, for the new and create action when the user is invalid.
I can refactor by encapsulating these dependencies in a method load_user_dependencies.
class UsersController < ApplicationController
def new
#user = User.new
load_user_dependencies
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
load_user_dependencies
render :action => "new"
end
end
private
def load_user_dependencies
#projects = Project.all
#companies = Company.all
end
end
Or by adding them as a helper_methods.
class UsersController < ApplicationController
helper_method :projects, :companies
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
render :action => "new"
end
end
def projects
#projects ||= Project.all
end
def companies
#companies ||= Company.all
end
end
I can also create a View Object
class UserView
def products
#products ||= Product.all
end
def companies
#companies ||= Company.all
end
end
class UsersController < ApplicationController
def new
#user = User.new
#user_view = UserView.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
#user_view = UserView.new
render :action => "new"
end
end
end
Other option is to use a Presenter
class UserPresenter < SimpleDelegator
def products
#products ||= Product.all
end
def companies
#companies ||= Company.all
end
end
class UsersController < ApplicationController
def new
#user = UserPresenter.new User.new
end
def create
#user = UserPresenter.new User.new(params[:user])
if #user.save
redirect_to #user
else
render :action => "new"
end
end
end
How do you guys usually deal with scenario?
It's a bit of a personal taste issue, but in our projects if it's suitable we do it in the view, and if it's complex we do it in a before_filter.
View - suitable if it's something that doesn't have any logic, no need to create a variable for this. Super useful if your form is contained in a partial as it's only done once so easily maintained.
<%= form.select :project_id, Project.all, :id, :name %>
If it's something that can change depending on any factors then a before_filter in controller:
MyController
before_filter :find_projects, :except => [:destroy, :some_method] # Will load the values but not for the destroy or some_method actions
def find_projects
#projects = Project.where(:some conditions => true)
end

Resources