My app on Heroku shows this error:
We're sorry, but something went wrong.
If you are the application owner check the logs for more information.
So I ran Heroku logs and guessed this could be the problem:
ActiveRecord::UnknownAttributeError (unknown attribute: user_id):
app/controllers/pins_controller.rb:14:in `new'
My Pins controller
class PinsController < ApplicationController
before_action :set_pin, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#pins = Pin.all
end
def show
end
def new
#pin = current_user.pins.build
end
def edit
end
def create
#pin = current_user.pins.build(pin_params)
if #pin.save
redirect_to #pin, notice: 'Pin was successfully created.'
else
render action: 'new'
end
end
def update
if #pin.update(pin_params)
redirect_to #pin, notice: 'Pin was successfully updated.'
else
render action: 'edit'
end
end
def destroy
#pin.destroy
redirect_to pins_url
end
private
# Use callbacks to share common setup or constraints between actions.
def set_pin
#pin = Pin.find(params[:id])
end
def correct_user
#pin = current_user.pins.find_by(id: params[:id])
redirect_to pins_path, notice: "Not authorized to edit this pin" if #pin.nil?
end
# Never trust parameters from the scary internet, only allow the white list through.
def pin_params
params.require(:pin).permit(:description, :image)
end
end
Anything wrong? Am I looking at the right place to debug?
Turns out I didn't do heroku run rake db:migrate. Thanks guys for that. Another error came up.
ArgumentError (missing required :bucket option):
app/controllers/pins_controller.rb:22:in `create'
Is this tied to Amazon Web Services?
You combined 2 issues into one question. For the first problem with the unknown attribute user_id you need to run:
heroku run rake db:migrate.
For the second problem with your ArgumentError (missing required :bucket option): error you need to set the heroku config to:
heroku config:set S3_BUCKET_NAME=nameOfYourBucket
I'd go in New action for plain
#pin = Pin.new
You are using your Create action to add the values from relations, so it should work fine
Other then that, use .new in New and .build in Create
Related
I'm currently creating a website that would allow a visitor to read a magazine online. I created a scaffold for the magazine itself, and another one for the pages, which belongs to the magazine. This way, I can create a multi upload for the pages while creating the magazine, and everything gets uploaded in the same time.
When I nest the pages resources inside the magazine's resources, as following:
resources :magazines do
resources :pages
end
I get "domain.com/magazines/<slug>/pages/id"
However, I had some issues with the id, because it can't be used to count the pages (since the id never goes back to 1), so I created a function inside the controller that would count the pages for me, and save each pages with a "page_number" value.
My question is the following: how, instead of the id, can I kindly ask my router to use the :page_number ?
I tried to create a custom route, which looked like this
resources :magazines do
get '/:page_number' => 'pages#show', as: :custom_page
end
But for an unknown reason, Rails tells me that my custom route simply doesn't exist, even though it exists when I type rake routes
Thank you in advance
Edit
Here is my magazine_controller.rb
class MagazinesController < ApplicationController
before_action :authenticate_user!, only: [:edit, :update, :destroy]
before_action :set_magazine, only: [:show, :edit, :update, :destroy]
def index
#magazines = Magazine.all
end
def show
end
def new
#magazine = Magazine.new
end
def edit
end
def create
#magazine = Magazine.new(magazine_params)
if #magazine.save
if params[:images]
(params[:image] || []).each_with_index do |image, index|
#magazine.pages.create(image: image, page_number: index + 1)
end
redirect_to #magazine, notice: 'Magazine was successfully created.'
else
render :new
end
end
end
def update
if #magazine.update(magazine_params)
if params[:images]
params[:images].each { |image|
#magazine.pages.create(image: image)
}
end
redirect_to #magazine, notice: 'Magazine was successfully updated.'
else
render :edit
end
end
def destroy
#magazine.destroy
redirect_to magazines_url, notice: 'Magazine was successfully destroyed.'
end
private
def set_magazine
#magazine = Magazine.friendly.find(params[:id])
end
def magazine_params
params.require(:magazine).permit(:titre, :apercu)
end
end
and here is page_controller.rb
class PagesController < ApplicationController
before_action :authenticate_user!, only: [:edit, :update, :destroy]
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)
if #page.save
redirect_to #page, notice: 'Page was successfully created.'
else
render :new
end
end
def update
if #page.update(page_params)
redirect_to #page, notice: 'Page was successfully updated.'
else
render :edit
end
end
def destroy
#page.destroy
redirect_to :back, notice: 'Page was successfully destroyed.'
end
private
def set_page
#page = Page.find(params[:id])
end
def page_params
params.require(:page).permit(:titre, :apercu)
end
end
Edit 2
Here is the output from development.log when trying to reach the page
Started GET "/magazines/magazine-54/pages/11" for 127.0.0.1 at 2016-12-12 11:04:45 +0100
Processing by PagesController#show as HTML
Parameters: {"magazine_id"=>"magazine-54", "id"=>"11"}
Completed 500 Internal Server Error in 2ms (ActiveRecord: 0.0ms)
NoMethodError (undefined method `pages' for nil:NilClass):
app/controllers/pages_controller.rb:49:in `set_page'
Rendering /var/lib/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
Rendering /var/lib/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered /var/lib/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (2.4ms)
Rendering /var/lib/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
Rendered /var/lib/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.2ms)
Rendering /var/lib/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered /var/lib/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.7ms)
Rendered /var/lib/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (13.8ms)
With these routes
resources :magazines do
resources :pages
end
you should be able to update PagesController and add/update following methods:
def magazine
#magazine = Magazine.find(params[:magazine_id])
end
def page
#page = #magazine.pages.find_by(page_number: params[:id])
end
to make it work you should have page_number column in Page model and has_many :pages association in Magazine model
I am using devise, and have a pieces model in my Ruby on Rails web app. A user has_many pieces. Right now, in my pieces controller, I have a method called correct_user, which allows only users who own the pieces to edit and destroy them. I want to add a line to this method which allows the user with a devise user id of 1 to be able to edit and destroy anyone else's pieces (if current_user.id ==1, then allow the edit/destroy actions). I have tried a few combinations, but I keep getting errors.
Here is my pieces controller: (the correct_user method is towards the end)
class PiecesController < ApplicationController
before_action :set_piece, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
respond_to :html
def index
#pieces = Piece.all
respond_with(#pieces)
end
def show
respond_with(#piece)
end
def new
#piece = current_user.pieces.build
respond_with(#piece)
end
def edit
end
def create
#piece = current_user.pieces.build(piece_params)
flash[:notice] = 'Piece was successfully created.' if #piece.save
respond_with(#piece)
end
def update
flash[:notice] = 'Piece was successfully updated.' if #piece.update(piece_params)
respond_with(#piece)
end
def destroy
flash[:notice] = 'Piece was successfully deleted.' if #piece.destroy
respond_with(#piece)
end
private
def set_piece
#piece = Piece.find(params[:id])
end
def correct_user
#piece = current_user.pieces.find_by(id: params[:id])
redirect_to pieces_path, notice: "Access Denied! Not authorized to edit this piece." if #piece.nil?
end
def piece_params
params.require(:piece).permit(:title, :image, :genre, :size, :price, :description, :status)
end
end
Thanks guys!
In correct_user, change the conditional on redirect_to to and return if #piece.nil? and current_user.id != 1, then add a new line below that: #piece = Piece.find(params[:id]) if current_user.id == 1, which will only run if the redirect_to ... and return does not.
(Also, you have current_user.pieces.find_by(id: ...), which can be just .find(...) for simplicity.)
I am building a small classifieds application for our community where folks can list products for sale using a form with params description and image only.
Both params are in the schema.rb
THE PROBLEM:
I have embedded the search bar on my index.html.erb and also created a show.html.erb which is blank. Currently the search bar does nothing except look pretty,
I am struggling to understand how to get the search wired up to interrogate the description param and deliver the results onto my show.html.erb.
NB: I would like the show.html.erb page and its search results to mirror my index page cosmetically and achieve this task without having to install any further gems.
class PinsController < ApplicationController
before_action :set_pin, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#pins = Pin.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 15)
end
def show
end
def new
#pin = current_user.pins.build
end
def edit
end
def create
#pin = current_user.pins.build(pin_params)
if #pin.save
redirect_to #pin, notice: 'Pin was successfully created.'
else
render :new
end
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 pins_url
end
private
# Use callbacks to share common setup or constraints between actions.
def set_pin
#pin = Pin.find_by(id: params[:id])
end
def correct_user
#pin = current_user.pins.find_by(id: params[:id])
redirect_to pins_path, notice: "Not authorized to edit this pin" if #pin.nil?
end
# Never trust parameters from the scary internet, only allow the white list through.
def pin_params
params.require(:pin).permit(:description, :image)
end
end
Change your index method to either have a search query or not.
def index
if params[:query]
#results = Advert.where('lower(description) LIKE ?', '%#{params[:query].downcase}%')
else
#results = Advert.all
end
end
You can also create filters using javascript or install either searchkick gem or if you need something REALLY simple install rails4-autocomplete
I'm building an app which consists on sharing résumés. I am using Devise gem. Each user is able to create only one résumé. I made the models and and their relations. Resume belongs_to User and User has_one 'Resume'.
After making the views, I wanted to test my app but I got the error: undefined methodbuild' for nil:NilClass`
Here is my ResumeController and my routes.rb
class ResumeController < ApplicationController
before_action :find_resume, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:show]
def show
# #resume = Resume.find_by(params[:id])
end
def new
#resume = current_user.resume.build
end
def create
#resume = current_user.resume.build(resume_params)
if #resume.save
redirect_to #resume, notice: "resume was successfully created"
else
render 'new'
end
end
def edit
end
def update
if #resume.update(pin_params)
redirect_to #resume, notice: "resume was successfully updated"
else
render 'edit'
end
end
def destroy
#resume.destroy
redirect_to root_path
end
private
def resume_params
params.require(:resume).permit(:title, :description)
end
def find_resume
#resume = resume.find(params[:id])
end
end
Routes.rb
Rails.application.routes.draw do
devise_for :users
resources :resume, except: [:index]
get 'static_pages/index'
root to: "static_pages#index"
end
I just want the user to be able to create only one Resume and then he will be able to share it.
Update: After following messanjah's answer there was another error coming from the _form.html.erb: undefined method resumes_path' for #<#<Class:0x00...>. Here is the gist with forms and model: goo.gl/XvW2LH So you can see all the files closely.
Without more knowledge of where the error is happening, I can only suggest some areas that might be suspect.
To build a has_one relationship, you must use the build_*association* constructor.
def new
#resume = current_user.build_resume
end
def create
#resume = current_user.build_resume(resume_params)
end
I am coding a Ruby on Rails app (rails 4), on an ubuntu machine.
I have created a new scaffold (model/view/controller) via rails g scaffold common_warnings , and it works just fine on my local machine (localhost:3000/common_warnings resolves to something appropriate), however when I upload this to my server, I get this error:
ActionController::RoutingError (uninitialized constant CommonWarningsController)
when trying to get mydomain.com/common_warnings.
I know that sometimes pluralization is a problem, these are the first lines of each of my controller and model files:
app/controllers/common_warnings_controller.rb
class CommonWarningsController < ApplicationController
app/models/common_warning.rb
class CommonWarning < ActiveRecord::Base
My rails app already has 30something tables in the database, I know I did have this problem a while ago but just can't work out how to fix this one. The pluralization seems to match what I do for loan_histories_controller.rb (also a multi-word name).
The output of rake routes is the same on my local machine and on the server. This is the relevant output:
rake routes | grep common
common_warnings GET /common_warnings(.:format) common_warnings#index
POST /common_warnings(.:format) common_warnings#create
new_common_warning GET /common_warnings/new(.:format) common_warnings#new
edit_common_warning GET /common_warnings/:id/edit(.:format) common_warnings#edit
common_warning GET /common_warnings/:id(.:format) common_warnings#show
PATCH /common_warnings/:id(.:format) common_warnings#update
PUT /common_warnings/:id(.:format) common_warnings#update
DELETE /common_warnings/:id(.:format) common_warnings#destroy
"The server" in this case is provided by AWS
This is my complete common warnings controller:
class CommonWarningsController < ApplicationController
before_action :set_common_warning, only: [:show, :edit, :update, :destroy]
before_action :signed_in_user
before_action :admin_user
# GET /common_warnings
# GET /common_warnings.json
def index
#common_warnings = CommonWarning.all
end
# GET /common_warnings/1
# GET /common_warnings/1.json
def show
end
# GET /common_warnings/new
def new
#new_or_edit = 'new'
#common_warning = CommonWarning.new
end
# GET /common_warnings/1/edit
def edit
#new_or_edit = 'edit'
end
# POST /common_warnings
# POST /common_warnings.json
def create
#common_warning = CommonWarning.new(common_warning_params)
respond_to do |format|
if #common_warning.save
format.html { redirect_to #common_warning, notice: 'Common warning was successfully created.' }
else
format.html { render action: 'new' }
end
end
end
# PATCH/PUT /common_warnings/1
# PATCH/PUT /common_warnings/1.json
def update
respond_to do |format|
if #common_warning.update(common_warning_params)
format.html { redirect_to #common_warning, notice: 'Common warning was successfully updated.' }
else
format.html { render action: 'edit' }
end
end
end
# DELETE /common_warnings/1
# DELETE /common_warnings/1.json
def destroy
#common_warning.destroy
respond_to do |format|
format.html { redirect_to common_warnings_url }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_common_warning
#common_warning = CommonWarning.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def common_warning_params
params.require(:common_warning).permit(:name)
end
def signed_in_user
store_location
redirect_to signin_url, notice: "Please sign in." unless signed_in?
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
Thanks in advance!
Fixed. It was a complicated problem to do with having multiple similar but not identical rails apps running from one server. I had forgotten to reset the connection to the schema migrations. Thanks to those who responded!