irb does not have access to my models (NameError: uninitialized constant) - ruby

I am receiving this error when trying to create a new 'Pin' in IRB. For example:
irb(main):001:0> #pin = Pin.first
NameError: uninitialized constant Pin
OR
irb(main):001:0> #pin = Pin.new
NameError: uninitialized constant Pin
I must of changed something as it was working before. Unfortunately, I cannot find the error
Here is my pins controller:
class PinsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :set_pin, only: [:show, :edit, :update, :destroy]
def index
#pins = Pin.all
end
def show
#pin = Pin.find params[:id]
end
def new
#pin = Pin.new
end
def edit
end
def create
#pin = Pin.new(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(params[:id])
redirect_to pins_path, notice: "Not allowed!" 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)
end
end
Here is are my associations, pin.rb
class Pin < ApplicationRecord
belongs_to :user
end
And my associations for User.rb:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :pins
end
and my routes
Rails.application.routes.draw do
resources :pins
devise_for :users
root "pages#home"
get "about" => "pages#about"
end

irb does not automatically load your Rails environment, which is why it does not have access to your models (or helpers, or database, or anything else). However, the "rails console" is an irb session that does load all of your Rails classes, database connections, etc.
To start the rails console:
rails c
Which is shorthand for:
rails console
This starts the rails console for your development environment. You can make it connect to your test environment:
rails c RAILS_ENV=test
or to your production environment:
rails c RAILS_ENV=production

Related

how to insert image field on reply form in forum app en ruby on rails?

i try to add the image field on reply form in my new app type forum.
the app containt the principal sujet and all users connected can reply on section replie.
now , i try to add the image field more older text field.
i use carrierwave to implement the feature.
but i receives this error message in terminal:
NoMethodError - undefined method `reimage_will_change!' for #
<Reply:0x000055cb9f2abc30>
Did you mean? Reimage_will_change!:
app/controllers/replies_controller.rb:8:in `create'
why subjection rails: reimage_will_change:
my i used "reimage" that variable field.
see complet message termianl:
Started POST "/discussions/pourquoi-intel-a-t-il-du-mal-a-suivre-la-loi-de-moore-la-loi-de-moore-est-elle-morte/replies" for ::1 at 2019-07-04 10:12:20 +0000
(1.5ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
↳ /home/chatln/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Processing by RepliesController#create as JS
Parameters: {"utf8"=>"✓", "reply"=>{"reply"=>"Amazon CEO Jeff Bezos gave this advice to those ", "reimage"=>#<ActionDispatch::Http::UploadedFile:0x000055d560cc1150 #tempfile=#<Tempfile:/tmp/RackMultipart20190704-14120-1uwpx6n.png>, #original_filename="Capture d’écran de 2019-06-10 11-08-07.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"reply[reimage]\"; filename=\"Capture d\xE2\x80\x99\xC3\xA9cran de 2019-06-10 11-08-07.png\"\r\nContent-Type: image/png\r\n">}, "commit"=>"Envoyer", "discussion_id"=>"pourquoi-intel-a-t-il-du-mal-a-suivre-la-loi-de-moore-la-loi-de-moore-est-elle-morte"}
User Load (1.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ /home/chatln/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Discussion Load (0.8ms) SELECT "discussions".* FROM "discussions" WHERE "discussions"."slug" = $1 LIMIT $2 [["slug", "pourquoi-intel-a-t-il-du-mal-a-suivre-la-loi-de-moore-la-loi-de-moore-est-elle-morte"], ["LIMIT", 1]]
####
↳ app/controllers/replies_controller.rb:55
Completed 500 Internal Server Error in 225ms (ActiveRecord: 24.9ms)
####
NoMethodError - undefined method `reimage_will_change!' for #<Reply:0x00007ffb6c716fa0>
Did you mean? Reimage_will_change!:
app/controllers/replies_controller.rb:8:in `create'
I think the error comes from line 55 of the replies controller at the level of set_discussion.
def set_discussion
#discussion = Discussion.friendly.find(params[:discussion_id])
end
and replies_controller complet
class RepliesController < ApplicationController
before_action :authenticate_user!
before_action :set_reply, only: [:edit, :update, :show, :destroy]
before_action :set_discussion, only: [:create, :edit, :show, :update, :destroy]
#before_action :find_discussions, only: [:create, :edit, :show, :update, :destroy]
def create
#reply = #discussion.replies.create(params[:reply].permit(:reply, :reimage, :discussion_id))
#reply.user_id = current_user.id
respond_to do |format|
if #reply.save
format.html { redirect_to discussion_path(#discussion) }
format.js # renders create.js.erb
else
format.html { redirect_to discussion_path(#discussion), notice: "Reponse non enregistrée, ressayer encore."}
format.js
end
end
end
def new
end
def destroy
#reply = #discussion.replies.find(params[:id])
#reply.destroy
redirect_to discussion_path(#discussion)
end
def edit
#discussion = Discussion.find(params[:discussion_id])
#reply = #discussion.replies.find(params[:id])
end
def update
#reply = #discussion.replies.find(params[:id])
respond_to do |format|
if #reply.update(reply_params)
format.html { redirect_to discussion_path(#discussion), notice: 'Reponse mise a jour...' }
else
format.html { render :edit }
format.json { render json: #reply.errors, status: :unprocessable_entity }
end
end
end
def show
end
private
def set_discussion
#discussion = Discussion.friendly.find(params[:discussion_id])
end
def set_reply
#reply = Reply.find(params[:id])
end
def reply_params
params.require(:reply).permit(:reply, :reimage, :discussion_id)
end
end
and model replies
class Reply < ApplicationRecord
mount_uploader :reimage, ReimageUploader
belongs_to :discussion
belongs_to :user
validates :reply, presence: true
extend FriendlyId
friendly_id :reply, use: [:slugged, :finders]
def should_generate_new_friendly_id?
reply_changed?
end
end
undefined method `x_will_change!' for # occures if you forget to add a column in your model's db table. If you have a model Reply and a ReimageUploader, with the uploader mounted as in the Carrierwave docs:
class Reply < ActiveRecord::Base
mount_uploader :reimage, ReimageUploader
end
Then the error will read
undefined method `reimage_will_change!' for #
To fix it add a column in a migration run the following in the console:
rails g migration AddReimageToUsers reimage:string
This will generate the following migration:
class AddReimageToUsers < ActiveRecord::Migration
def change
add_column :replies, :reimage, :string
end
end
Migrate it to apply the change (write down the below command in the console):
rake db:migrate

Can't create sessions for some of my STI User types using Blizzard's omniauth-bnet gem

I'm working on a Rails 5 app using the omniauth-bnet gem, not devise, have a Single Sign On through that gem, and have a few User types, using Single Table Inheritance. For whatever reason, the admin type can login fine, but the average User cannot create a session. Here's some of the relevant code.
items_controller.rb:
before_action :check_authorization, except: [:show]
before_action :check_for_email, except: [:show]
...
private
def check_authorization
unless current_user
redirect_to root_path
end
end
def check_for_email
unless current_user.email
redirect_to signup_add_email_url
end
end
sessions_controller.rb:
class SessionsController < ApplicationController
def create
begin
#user = User.from_omniauth(request.env['omniauth.auth'])
session[:user_id] = #user.id
flash[:success] = "Well met, #{#user.name}!"
rescue
flash[:warning] = "There was an error while trying to create your
account..."
end
redirect_to items_path
end
...
admin_user.rb:
class AdminUser < User
end
normal_user.rb:
class NormalUser < User
end
user.rb:
class User < ApplicationRecord
...
class << self
def from_omniauth(auth_hash)
user = find_or_create_by(name: auth_hash['info']['battletag'], uid:
auth_hash['uid'], provider: auth_hash['provider'])
user.name = auth_hash['info']['battletag']
user.uid = auth_hash['uid']
user.token = auth_hash['credentials']['token']
user.save!
user
end
end
routes.rb:
...
# Auth
get '/auth/:provider/callback', to: 'sessions#create'
...
The logs show that my NormalUser type session never gets created. Yet the AdminUser type doesn't have any problem logging in...
Any ideas? I've tried everything I can google or think of.

Do I have to specify actions in routes.rb?

While I'm reading Rails 4 in Action, I'm trying to implement my own application, so it doesn't look same as in the book.
The book's corresponding commit is Section 7.2.3: Only admins can create or delete projects
In my case, admins can only delete the item (item corresponds to the project in the book.).
My repo https://github.com/tenzan/shop and deployed http://ichiba-demo.herokuapp.com/
The rule I want to apply is:
A regular user (you can login with staff#example.com/password) can do everything except destroy action.
Admin (admin#example.com/password) only can destroy.
To realise that I have:
In admin/items_controller.rb:
class Admin::ItemsController < Admin::ApplicationController
def destroy
#item = Item.find(params[:id])
#item.destroy
flash[:notice] = 'Item has been deleted.'
redirect_to items_path
end
private
def item_params
params.require(:item).permit(:name, :quantity)
end
end
In controllers/items_controller.rb:
class ItemsController < ApplicationController
before_action :set_item, only: [:show, :edit, :update]
def index
#items = Item.all
end
def new
#item = Item.new
end
def create
#item = Item.new(item_params)
if #item.save
flash[:notice] = 'Item has been created.'
redirect_to #item
else
flash.now[:alert] = 'Item has not been created.'
render 'new'
end
end
def show
end
def edit
end
def update
if #item.update(item_params)
flash[:notice] = 'Item has been updated.'
redirect_to #item
else
flash.now[:alert] = 'Item has not been updated.'
render 'edit'
end
end
private
def set_item
#item = Item.find(params[:id])
rescue ActiveRecord::RecordNotFound
flash[:alert] = 'The item could not be found.'
redirect_to items_path
end
def item_params
params.require(:item).permit(:name, :quantity)
end
end
In routes.rb:
Rails.application.routes.draw do
namespace :admin do
root 'application#index'
resources :items, only: :destroy
end
devise_for :users
root 'items#index'
resources :items, only: [:index, :show, :edit, :update, :new, :create] do
resources :comments
end
end
Questions:
Do I have to specify actions in the routes.rb, as I already have specified who can use what actions in their corresponding controllers? I didn't notice any change when I remove them from the routes.rb...
Am I violating DRY concept, when I specify actions in 2 places, i.e. in the routes.rb and controllers/items_controllers.rb ?
I'll be happy if you point out other places to improve to meet best practice.
PS: The subject maybe vague, please feel free to edit it.
Do I have to specify actions in the routes.rb, as I already have
specified who can use what actions in their corresponding controllers?
Yes. For instance, if you'd have only one action in items_controller.rb controller (let say show), and left
resources :items do # no specified actions
#...
end
in routes.rb it would generate all routes for items controller (for new, create, edit, destroy, update etc). But specifying actions in routes.rb you limit generated routes to only needed.
Am I violating DRY concept, when I specify actions in 2 places, i.e.
in the routes.rb and controllers/items_controllers.rb ?
No. Because you actually specify actions in controller, in routes.rb you only specify routes.
I'll be happy if you point out other places to improve to meet best
practice.
This line:
resources :items, only: [:index, :show, :edit, :update, :new, :create] # better to use %i() notation, eg only: %i(index show edit update new create)
could be written as:
resources :items, except: :destroy
Regarding your admin user - to allow only him to destroy, just check if current_user is admin. If you'll have more, than one action which is allowed to be performed by only admin, you can create before_action in controller:
before_action :check_admin?, only: %i(destroy another_action)
private
def check_admin?
# your logic to check, if user is admin
end
You can also be interested in going through Ruby style guide.
Even though you're not violating DRY directly, you're muddying up the REST architecture by moving a single entity's actions to different controllers. You don't need a specific controller or namespace for admins - you just need to assert that the user is an administrator before proceeding with the delete action.
Since you have already added the admin column to your devise model, you can move the delete action to ItemsController
def destroy
if current_user.try(:admin?)
#item = Item.find(params[:id])
#item.destroy
flash[:notice] = 'Item has been deleted.'
else
flash[:alert] = 'Only admins can delete items.'
end
redirect_to items_path
end
Your routes would be cleaner since your admin namespace would be used only for user moderation. The only route for items would be:
resources :items do
resources :comments
end

#users variable empty. forget to pass the collection object for will_paginate?

Problem localhost:3000/users/ won't display
I enter humbly as I am trying to make it through the rails tutorial for the first time. I am in chapter 10 and I have been trouble shooting this for 5 hours. When I attempt to visit localhost:3000/users/ I get an error (I believe this has something to do with factory_girl) that explain that the #users variable is empty and that I forgot to pass a collection object for will_paginate.
I'm currently at chapter 10, section 10.23 and each time I run:
$ bundle exec rake db:reset $ bundle exec rake db:populate
$ bundle exec rake db:test:prepare
I get an error explaining that
rake aborted!
Factory already registered: micropost
This is my second time trying this chapter as I encountered problems the first time and started from chapter 9. Please help and be clear and detailed when providing directions. I am happy to post whatever files that will be helpful.
Here is my index.html.erb - I save these as HTML, should they be saved as ruby files instead?
<% provide(:title, 'All users') %>
<h1>All users</h1>
<%= will_paginate %>
<ul class="users">
<%= render #users %>
</ul>
<%= will_paginate %>
Here is my users controller
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update, :destroy]
before_filter :correct_user, only: [:edit, :update]
before_filter :admin_user, only: :destroy
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page])
end
end
def new
#user = User.new
end
def index
#title = "All users"
#users = User.paginate(:page => params[:page])
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Do more of the things you love!"
redirect_to #user
else
render 'new'
end
end
def edit
end
def update
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
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 signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
In your Users controller, make sure you have #users and if you are using will_paginate, make sure you call .paginate(page: params[:page], per_page: 20] and in your view, have <%= will_paginate #users %>.
/users should point to UsersController#index. Make sure you are assigning the collection #users.
For instance it could look like this at the most basic level:
def index
#users = User.all # not paginated
#users = User.paginate(page: params[:page]) # paginated
end
As far as the test database error, I'm guessing that's because you define a :micropost factory more than once.
Instead of #user = User.find(params[:id]) this you should use
#users = User.paginate(page: params[:page])

params[:token] not set with devise

I'm trying to implement Devise but new to it.
When I request .../api/v1/projects.json, I get 'undefined method admin? for nil:NilClass', which I'm assuming happens because params[:token] is not being set:
class Api::V1::ProjectsController < Api::V1::BaseController
def index
respond_with(Project.for(current_user))
end
end
--
class Project < ActiveRecord::Base
...
def self.for(user)
user.admin? ? Project : Project.readable_by(user)
end
end
--
class User < ActiveRecord::Base
before_save :ensure_authentication_token
devise :database_authenticatable, :registerable, :token_authenticatable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
...
end
--
class Api::V1::BaseController < ActionController::Base
before_filter :authenticate_user
respond_to :json
private
def authenticate_user
#current_user = User.find_by_authentication_token(params[:token])
end
def current_user
#current_user
end
end
Does anyone know how/where to set params[:token] with Devise?
Apparently I misunderstood the documentation, and token is passed in through the URL:
.../api/v1/projects.json?token=s28seWhpPVWkhMU7sszM
Problem solved, I guess.

Resources