#<NoMethodError: undefined method `token?' for #<User: > - ruby-on-rails-5

When I try to create a user,I am facing this error
"exception": "#<NoMethodError: undefined method `token?' for #<User:0x000056037eec27a0>>",
The db of the user is
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :name
t.string :email
t.string :phone
t.string :token
t.string :password_digest
t.timestamps
end
add_index :users, unique: true
end
end
My code for user model is
class User < ApplicationRecord
has_secure_token
has_secure_password
has_many :projects , dependent: :destroy
end
My controller code is
class UsersController < ApplicationController
def new
#user = User.new
end
# POST /users
def create
#user = User.new(user_params)
if #user.save
render json: #user, status: :created, location: #user
else
render json: #user.errors, status: :unprocessable_entity
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def user_params
Rails.logger.info "#{params.inspect}"
params.require(:user).permit(:name, :email, :phone, :password)
end
end
The data I am sending through the POST request is
{
"user":{
"name":"pranesh",
"email":"pranesh#gmail.com",
"phone":"987654321",
"password":"helloworld"
}
}
When I send the request,I am facing this error,
"status": 500,
"error": "Internal Server Error",
"exception": "#<NoMethodError: undefined method `token?' for #<User:0x000056037eec27a0>>",
I am using rails 5.2.1

has_secure_token :token
Try this

Related

ActiveRecord_Associationundefined method `reviews' for #<Post::ActiveRecord_Associations_CollectionProxy:>s_CollectionProxy

I have 3 models in my application namely - user, post and comments. They are associated like this
A user can have posts
A posts belongs to a user
A post can have many reviews
A review belongs to a user
Posts Model
class Post < ApplicationRecord
belongs_to :user
has_many :comments, dependent: :destroy
validates :title, presence: true
validates :body, presence: true
end
User Model
class User < ApplicationRecord
before_create { generate_token(:auth_token) }
before_save { self.email = email.downcase }
has_secure_password
has_many :posts
validates :name, presence: true
validates :email, presence: true, uniqueness: true
validates :password, confirmation: true
validates :password_confirmation, presence: true, unless: Proc.new { |a| !a.new_record? && a.password.blank? }
def send_password_reset
generate_token(:reset_password_token)
self.reset_password_sent_at = Time.zone.now
save!
UserMailer.password_reset(self).deliver
end
def generate_token(column)
begin
self[column] = SecureRandom.urlsafe_base64
end while User.exists?(column => self[column])
end
end
Review Model
class Review < ApplicationRecord
belongs_to :user
end
User Controller - show method
def show
#user = User.find(params[:id])
#posts = #user.posts
#reviews = #posts.reviews //This line shows error
end
I think something is wrong in the way i am associating these models.
I want to show comments made on a post with that post. I show from posts users controller....but i when i tried to display comments the same way. I
I had manually gone and made a comment to post in rails console.
Review table from schema
create_table "reviews", force: :cascade do |t|
t.string "comment"
t.string "user_id"
t.string "post_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
Can see two issues in the code.
1 - you haven't define the relationship between post and review in review model.
class Review < ApplicationRecord
belongs_to :user
belongs_to :post
end
2 - you are trying to get reviews out of posts relation. If you want to get all the reviews for a given user. you should probably need
def show
#user = User.find(params[:id])
#posts = #user.posts
#reviews = #user.reviews
end
or you may have to load reviews for each post in the view by
post.reviews

Pull data from multiple tables in Rails

I am new in Ruby on Rails and I am trying to make a book registration website. Everything works fine except category section. When a user assign a category to his book, my database copies book_categories.id and put it in book.book_categories_id. The website also have a profile page, where you can view user's book(s). My problem is to display a category.name, I searched a lot of similar problems but I have not found the right answer.
Here is my book controller:
before_action :set_book, except: [:index, :new, :create]
before_action :authenticate_user!, except: [:show]
def show
#photos = #book.photos
end
def index
#books = current_user.books
end
def new
#book = current_user.books.build
end
def create
#book = current_user.books.build(books_params)
if #book.save
redirect_to listing_book_path(#book), notice: "Saved."
else
flash[:alert] = "Failed."
render :new
end
end
private
def set_book
#book = Book.find(params[:id])
end
def book_params
params.require(:book).permit(:book_categories_id, :book_name, :summary, :address, :price, :company_name)
end
As long as I understand, I have to allow my controller to have access to my category table but I do not know how. Also, all of my categories store in seed.rb.
This is my BookCategory.rb model:
class BookCategory < ActiveRecord::Base
has_many :books, :foreign_key => :book_categories_id
end
Book.rb model:
class Book < ApplicationRecord
belongs_to :user, :foreign_key => 'user_id'
has_many :photos, dependent: :delete_all
validates :book_name, presence: true
validates :book_categories_id, presence: true
def cover_photo
if self.photos.length > 0
self.photos[0].image.url
else
"default/image-default.jpg"
end
end
end
My schema.rb:
create_table "book_categories", force: :cascade do |t|
t.string "name"
t.string "subcategory"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "book", force: :cascade do |t|
t.string "book_name"
t.text "summary"
t.string "address"
t.decimal "price", precision: 8, scale: 2
t.boolean "active"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.float "latitude"
t.float "longitude"
t.string "company_name"
t.integer "book_categories_id"
t.index ["book_categories_id"], name: "index_books_on_book_categories_id"
end
Usually, when I type #book_categories.name, I get an error:
undefined method `name' for nil:NilClass
And at the very end, it says Parameters: {"id"=>"15"} whereas the category.id is different, and it passes book.id instead.
What I am doing wrong?
First fix the naming problem you have going. I don't know how the books table got called "book" instead of "books" in the schema, but you might have to fix that first.
Then category should be singular everywhere except the database table name. You need to make a migration to fix the foreign key and its index in the books table something like this:
class FixCategoryNaming < ActiveRecord::Migration
def change
remove_column :books, :book_categories_id
add_reference :books, :book_category, index: true, foreign_key: true
end
end
Then run rails db:migrate and check the schema looks ok
Then in the BookCategory class change the line to simply
has_many :books
You need to add this line to your Book class
belongs_to :book_category
and change the validation for book_category to be this
validates :book_category_id, presence: true
Then in the view for book index you have a #books variable. You can get the book name and category name for each book like this:
<% #books.each do |book| %>
<p><%= book.book_name %></p>
<p><%= book.book_categories.name %></p>
<% end %>
I think you need to setup as has_many through relationship. This is a good place to start http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

has_many relationship with images in the def create

I am trying to create many images for a single product.
Since the number of images per product is as many as the user wants to enter I have created 2 separate models, product and product_image.
Product has many product_images
and product_images belongs_to product
I'm almost certain that this section of code is the problem (this is the product_image controller)
def create
#product_image = ProductImage.new(params[:product_image])
#product = #product_image.product
if #product_image.save
#product_image.product_id = #product.id
#product_image.save
redirect_to #product_image, notice: 'Product image was successfully created.'
else
render :template => "products/edit"
end
end
At the moment the code allows me to upload an image via paperclip but totally disregards the product_id and just puts the product_image_id in that field instead.
I checked the db through the cmd line to see this.
So how do I get an image to be created with an ID of a particular product? I've searched this site but the questions that exist do seem to offer the solution that I require.
Thanks for any help you can offer.
Here are the migrations that I used for the models relating to products and product_images
I apologize for the mess, I was very indecisive in my initial development which caused lost of little changes to be made as I gained more knowledge about the whole rails system
products
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.string :name
t.text :description
t.string :image_url
t.decimal :price, precision: 8, scale: 2
t.timestamps
end
end
end
and, products
class AddColumnsToProducts < ActiveRecord::Migration
def change
drop_table :products
create_table :products do |t|
t.string :product_title
t.text :product_desc
t.string :product_image_url
t.decimal :price, precision: 8, scale: 2
t.timestamps
end
end
end
and, products
class AddColumnToProducts < ActiveRecord::Migration
def change
add_column :products, :department, :string
end
end
and, products
class AddMoreColumnsToProducts < ActiveRecord::Migration
def change
add_column :products, :display_on_home_page, :boolean, default: false
add_column :products, :is_highight_product, :boolean, default: false
end
end
and, products
class RenameIsHighightProductInProducts < ActiveRecord::Migration
def up
rename_column :products, :is_highight_product, :is_highlight_product
end
def down
end
end
and, products
class RenameProductImageUrlInProducts < ActiveRecord::Migration
def up
rename_column :products, :product_image_url, :image_url
end
def down
end
end
and product images table created
class CreateProductImages < ActiveRecord::Migration
def change
create_table :product_images do |t|
t.integer :product_id
t.string :title
t.text :description
t.string :image_file_name
t.string :image_content_type
t.integer :image_file_size
t.datetime :image_updated_at
t.timestamps
end
end
end
and, products
class AlterTableProducts < ActiveRecord::Migration
def up
end
remove_column :products, :image_url
add_column :products, :product_image_id, :integer
def down
end
end
and, product_images
class AddColumnToProductImages < ActiveRecord::Migration
def change
add_column :product_images, :image_path, :string
end
end
and, product_images
class RenameColumnImagePathInProductImages < ActiveRecord::Migration
def up
rename_column :product_images, :image_path, :image_url
end
def down
end
end
and, product_images
class AddProductTitleColumnToProductImages < ActiveRecord::Migration
def change
add_column :product_images, :product_title, :string
end
end
and finally, products
class DropPriceFromProductsAndAddPriceToProducts < ActiveRecord::Migration
def up
end
remove_column :products, :price
add_column :products, :price, :decimal, :precision => 8, :scale => 2
def down
end
end
I am not sure what is going wrong because there is a little too less info in your question. But let me show quickly, how this should be set up (simplified).
new rails app:
rails new stack_product
creating the models
rails g model product
rails g model image
You get all this (you have to add the attr_accessible attributes by hand here)
app/models/product.rb
class Product < ActiveRecord::Base
attr_accessible :title, :description
has_many :images
end
app/models/image.rb
class Image < ActiveRecord::Base
attr_accessible :name, :path, :product_id
belongs_to :product, foreign_key: "product_id"
end
db/migrations/20131011195035_create_products.rb
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.primary_key :id
t.string :title
t.string :description
t.string :image_url
t.timestamps
end
end
end
20131011195421_create_images.rb
class CreateImages < ActiveRecord::Migration
def change
create_table :images do |t|
t.primary_key :id
t.integer :product_id
t.string :name
t.string :path
t.timestamps
end
end
end
use rails console in the terminal.
rails console
the fire:
Product.create({title: 'Ford Mustang', description: 'The one and only Shelby'})
...
Image.create({product_id: 1, name: 'Image Mustang', path: '/images/mustang.png'})
Image.create({product_id: 1, name: 'Image Mustang from behind', path: '/images/mustang2.png'})
then you can query the objects
p = Product.find(1)
Product Load (0.2ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", 1]]
=> #<Product id: 1, title: "Ford Mustang", description: "The one and only Shelby", image_url: nil, created_at: "2013-10-11 20:14:06", updated_at: "2013-10-11 20:14:06">
Image.where("product_id=?", p.id)
Image Load (0.3ms) SELECT "images".* FROM "images" WHERE (product_id=1)
=> [#<Image id: 1, product_id: 1, name: "Image Mustang", path: "/images/mustang.png", created_at: "2013-10-11 20:14:09", updated_at: "2013-10-11 20:14:09">, #<Image id: 2, product_id: 1, name: "Image Mustang from behind", path: "/images/mustang2.png", created_at: "2013-10-11 20:14:26", updated_at: "2013-10-11 20:14:26">]
So this works fine. If you would create forms for this, you would have one for the products and another one for the images. The images form would have a dropdown with all the products (productname and value with id). The dropdown for the products would be named product_id and then the product's id would be saved in the image table as product_id.
You should maybe scaffold all this to see how it is be done by Rails.

Using paperclip with factory girl, no image handler error

I am trying to use paperclip with factory_girl gem but getting a "no handler found
error" message.
test_should_update_category(CategoriesControllerTest):
Paperclip::AdapterRegistry::NoHandlerError: No handler found for "/system/categories/images/000/000/001/original/tel1.JPG?1354197869"
Factory girl file:
FactoryGirl.define do
factory :category do
name "MyString"
description "MyText"
image { File.new(File.join(Rails.root, 'test','tel1.JPG')) }
end
end
category migration ::---------------
class CreateCategories < ActiveRecord::Migration
def up
create_table :categories do |t|
t.string :name
t.text :description
t.string :image
t.timestamps
end
add_attachment :categories, :image
end
model:
class Category < ActiveRecord::Base
attr_accessible :description, :image, :name
has_attached_file :image, :styles => { :thumb => "100x100>" }
end
category controller test file:
require 'test_helper'
class CategoriesControllerTest < ActionController::TestCase
setup do
#category = FactoryGirl.create(:category)
end
I make it to work with the following code in my app / factory:
FactoryGirl.define do
factory :upload do
permalink "unique"
upload Rack::Test::UploadedFile.new(Rails.root + 'spec/files/uploads/unique.jpg', 'image/jpg')
end
end
So in your app you should change your factory of category to something like this:
FactoryGirl.define do
factory :category do
name "MyString"
description "MyText"
image Rack::Test::UploadedFile.new(Rails.root +'test/tel1.JPG', 'image/jpg')
end
end

Rails 3.2 - accepts_nested_attributes_for and join models

I have the following models: user, role, user_role (user_role is a join model)
I am trying to edit a user's roles using checkboxes on the user#edit page. Here's my attempt, I feel like I'm missing something significant, or taking the wrong approach.
user.rb
has_many :user_roles, dependent: :destroy
has_many :roles, through: :user_roles
attr_accessible :user_roles_attributes
accepts_nested_attributes_for :user_roles, reject_if: lambda { |a| a[:role_id] == 0 }, allow_destroy: true
def has_role?(role_sym)
roles.any? { |r| r.name.underscore.to_sym == role_sym.downcase }
end
def setup_roles!
Role.all.each { |role|
user_roles.build(user_id: id, role_id: role.id) unless has_role?(role.name.to_sym)
}
end
user_role.rb
belongs_to :user
belongs_to :role
delegate :name, to: :role
role.rb
has_many :user_roles
has_many :users, through: :user_role
users_controller.rb
def edit
#user = User.find(params[:id])
#user.setup_roles!
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
flash[:notice] = 'User was successfully updated.'
redirect_to edit_user_path(#user)
else
render :edit
end
end
users/edit.html.haml
= form_for #user do |f|
= f.fields_for(:user_roles) do |role_form|
= role_form.check_box :role_id, {}, role_form.object.role_id, 0
= role_form.hidden_field :user_id
= role_form.label :name, role_form.object.name
= f.submit 'Update'
Here is my solution. I received a lot of help from This Post at RubySource. The way the checkbox is setup, it will destroy a UserRole if "unchecked", and only create it when it is "checked" (why the '0', '1' is on that line.)
users_controller.rb
def edit
#user = User.find(params[:id])
#user.setup_roles!
end
user.rb
def has_role?(role_sym)
roles.any? { |r| r.name.underscore.to_sym == role_sym.downcase }
end
def setup_roles!
Role.all.each { |role|
user_roles.build(role: role) unless has_role?(role.name.to_sym)
}
end
users/edit.html.haml
= form_for #user do |f|
= f.fields_for :user_roles do |builder|
= builder.check_box :_destroy, { checked: builder.object.persisted? }, '0', '1'
= builder.label :_destroy, builder.object.role.name
= builder.hidden_field :role_id
= f.submit 'Update'