Postman problems in post request - ruby

I'm trying to use postman with a post request for mi controller "comments". This rquest show me the following error:
"NoMethodError (undefined method `news'..."
Here is the comment model:
class Comment < ApplicationRecord
include Discard::Model
belongs_to :user, optional: true
belongs_to :news, optional: true
validates :news_id, presence: true
validates :user_id, presence: true
validates :body, presence: true
end
and here is the controller:
module Api
module V1
class CommentsController < ApplicationController
before_action :authenticate_request, only: %i[index create update destroy]
before_action :set_comment, only: %i[update destroy]
before_action :authorize_user, only: %i[show create update destroy]
def index
#comment = Comment.order('created_at DESC')
render json: CommentSerializer.new(#comment,
fields: { comment: :body })
.serializable_hash, status: :ok
end
def create
#comment = Comment.new(comment_params)
#comment.user = #current_user
#comment.news = #current_user.news.find(params[:news_id])
if #comment.save
render json: CommentsSerializer.new(#comment).serializable_hash, status: :created
else
render_error
end
end
def update
if ownership?
#comment = Comment.update(comment_params)
render json: CommentSerializer.new(#comment).serializable_hash
else
render json: #comment.errors, status: :unprocessable_entity
end
end
def destroy
if ownership?
#comment.discard
head :no_content
else
render json: { error: 'unauthorized' }, status: :unauthorized
end
end
private
def set_comment
#comment = Comment.find(params[:id])
end
def comment_params
params.require(:comment).permit(:body)
end
def render_error
render json: { errors: #comment.errors.full_messages },
status: :unprocessable_entity
end
def render_unauthorized
render status: :unauthorized, json: {
errors: [I18n.t('errors.controllers.unauthorized')]
}
end
end
end
end
When I send a request for post in postman, it show the following problem:
NoMethodError (undefined method `news' for #<User id: 27, first_name: "rafa", last_name: "quinteros", email: "rafa4#email.com", password_digest: [FILTERED], photo: nil, role_id: 1, created_at: "2022-08-05 13:42:51.360055000 -0300", updated_at: "2022-08-05 13:42:51.360055000 -0300", discarded_at: nil>):

Well, your comment.user receives #current_user, but the user doesn't have news method/relationship. You should write a news method to stop this error.

Related

Using find_or_create_by! in before_action filter

I have a weird behaviour when using User.find_or_create_by! in before_action filter as follows:
class ApplicationController < ActionController::API
before_action :authorize_request
attr_reader :current_user
private
def authorize_request
#current_user = (AuthorizeApiRequest.new(request.headers).call)[:user]
end
end
Then in AuthorizeApiRequest I'm checking for existence or creating a new User by name:
class AuthorizeApiRequest
def initialize(headers = {})
#headers = headers
end
def call
{
user: user
}
end
def user
if decoded_auth_token && decoded_auth_token[:sub]
#user ||= User.find_or_create_by!(username: decoded_auth_token[:sub])
Rails.logger.silence do
#user.update_column(:token, http_auth_header)
end
#user
end
rescue ActiveRecord::RecordInvalid => e
raise(
ExceptionHandler::InvalidToken,
("#{Message.invalid_token} #{e.message}")
)
end
end
Example of UsersController:
class UsersController < ApplicationController
def me
if user_info_service.call
json_response current_user, :ok, include: 'shop'
else
raise AuthenticationError
end
end
private
def user_info_service_class
#user_info_service_class ||= ServiceProvider.get(:user_info_service)
end
def user_info_service
#user_info_service ||= user_info_service_class.new(user: current_user)
end
end
What is weird is that sometimes the User is created twice with the same username, sometimes not.
I'm using Ember JS in the front and another call is made to shops right after the authentication with JWT. All the routes are protected. I have the impression that calling current_user is not always in the same thread or sth like that and it results in having 2 identical users:
- the first one with just a username attribute set
- another one with all the others User attributes.
Here is the User model:
class User < ApplicationRecord
validates :username, presence: true, uniqueness: { case_sensitive: false }, on: :create
validates :shop_identifier, numericality: { only_integer: true, greater_than: 0 }, on: :update
validates :first_name, presence: true, on: :update
validates :last_name, presence: true, uniqueness: { case_sensitive: false, scope: :first_name }, on: :update
before_update do |user|
user.first_name = first_name.strip.capitalize
user.last_name = last_name.strip.upcase
end
Any ideas ? Thank you

Add a record in Many to many relation fails

I have a many to many connection in Rails applications, it looks like this:
class Workspace
has_and_belongs_to_many :users, dependent: :destroy
end
class User
has_and_belongs_to_many :workspaces
end
class UserWorkspace
belongs_to :user
belongs_to :workspace
end
Schema:
create_table :users_workspaces do |t|
t.integer :user_id
t.integer :workspace_id
t.integer :role, default: 0
t.timestamps null: false
end
Then I want to create a new record like this:
#user.workspaces.create(:workspace_id => #workspace.id, :role => 1)
or this
#user.workspaces << #workspace
and have an error in logs:
(0.0ms) begin transaction
(0.0ms) begin transaction
(0.1ms) rollback transaction
(0.1ms) rollback transaction
Completed 500 Internal Server Error in 207ms (ActiveRecord: 5.5ms)
Completed 500 Internal Server Error in 207ms (ActiveRecord: 5.5ms)
ActiveRecord::UnknownAttributeError (unknown attribute 'workspace_id' for Workspace.):
app/controllers/sessions_controller.rb:10:in `block in sign_up'
app/controllers/sessions_controller.rb:4:in `sign_up'
What am I doing wrong?
PS Controller:
def sign_up
respond_to do |format|
#user = User.new(user_params)
if #user.save
#workspace = Workspace.new(title: "#{#user.name}'s workspace")
#workspace.save
puts "workspace id: #{#workspace.id}"
#user.workspaces.create(:workspace_id => #workspace.id, :role => 1)
puts "workspaces count: #{#user.workspaces.count}"
#user.workspace = #workspace
#user.update_attributes(user_params)
flash.now[:success] = 'Welcome! Please check activation letter in your email box.'
format.js { render 'signup_message' }
else
format.js { render 'render_signup_errors' }
end
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :name, :workspace_id)
end
There are couple of problems with your code. For example, you are creating workspaces that are already created (#user.workspaces.create), or permitting a :workspace_id that is not used, etc.
Pleas see code below:
def sign_up
respond_to do |format|
#user = User.new(user_params)
if #user.save
#workspace = Workspace.new(title: "#{#user.name}'s workspace")
if #workspace.save
# Like this
UserWorkspace.create(user: #user, workspace: #workspace, role: 1)
# Or, like this
#user.user_workspaces.create!(workspace_id: #workspace.id, role: 1)
end
flash.now[:success] = 'Welcome! Please check activation letter in your email box.'
format.js { render 'signup_message' }
else
format.js { render 'render_signup_errors' }
end
end
end
private
# You don't need :workspace_id since you are not using it anywhere
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :name)
end

undefined method `activation_digest=' for #<User:0x007fe3810ceba0> Michael Hartl's book

I am working through Michael Hartl's Rails book and I am about halfway through chapter 10-working on account activation.
I had everything working with the mailers but then when I tried to add a new user, I got the following error message: "undefined method `activation_digest=' for #"
I have been trying to follow along in the book the best that I can. I have my users_controller.rb here:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update]
before_action :correct_user, only: [:edit, :update]
def new
#user = User.new
end
def index
#users = User.paginate(page: params[:page], :per_page => 10)
end
def show
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
else
render 'edit'
end
end
def edit
#user = User.find(params[:id])
end
#confirms if a user is logged in
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please Log In."
redirect_to login_url
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
Here is my Model/user.rb:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token
before_save :downcase_email
before_create :create_activation_digest
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
# Returns the hash digest of the given string.
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
#Returns a random token
def User.new_token
SecureRandom.urlsafe_base64
end
#Remembers a user in the database for use in persistent sessions
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
#Returns true if the given token matches the digest
def authenticated?(remember_token)
return false if remember_digest.nil?
BCrypt::Password.new(remember_digest).is_password?(remember_token)
end
#forgets a user
def forget
update_attribute(:remember_digest, nil)
end
private
# Converts email to all lower-case.
def downcase_email
self.email = email.downcase
end
# Creates and assigns the activation token and digest.
def create_activation_digest
self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token)
end
end
The routes I have this:
root 'static_pages#home'
get 'sessions/new'
get 'users/new'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users
resources :account_activations, only: [:edit]
Please let me know if anything more is needed to be seen. I do have my App up on Github under the name sample_app, my username is ravenusmc.
Looking at your project on Github, your User model doesn't have an activation_token or activation_digest column, nor does the model define them as attributes.
Your User model is trying to write to these columns in the User#create_activation_digest function which is most likely causing the issue.
You'll need to write a migration to add those columns to your User model or add them is attributes (ie attr_accessor) if they are not meant to be persisted.

Uploading image in paperclip lags my server for 3 minutes and then gives me error

This is my controller
class PinsController < ApplicationController
before_action :authenticate_user!, except: [:index]
before_action :set_pin, only: [:show, :edit, :update, :destroy]
# GET /pins
# GET /pins.json
def index
#pins = Pin.all
end
# GET /pins/1
# GET /pins/1.json
def show
end
# GET /pins/new
def new
#pin = current_user.pins.new
end
# GET /pins/1/edit
def edit
#pin = current_user.pins.find(params[:id])
end
# POST /pins
# POST /pins.json
def create
#pin = current_user.pins.new(pin_params)
respond_to do |format|
if #pin.save
format.html { redirect_to #pin, notice: 'Pin was successfully created.' }
format.json { render :show, status: :created, location: #pin }
else
format.html { render :new }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /pins/1
# PATCH/PUT /pins/1.json
def update
#pin = current_user.pins.find(params[:id])
respond_to do |format|
if #pin.update(pin_params)
format.html { redirect_to #pin, notice: 'Pin was successfully updated.' }
format.json { render :show, status: :ok, location: #pin }
else
format.html { render :edit }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
# DELETE /pins/1
# DELETE /pins/1.json
def destroy
#pin = current_user.pins.find(params[:id])
#pin.destroy
respond_to do |format|
format.html { redirect_to pins_url, notice: 'Pin was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_pin
#pin = Pin.find(params[:id])
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
This is my model
class Pin < ActiveRecord::Base
attr_accessible :description, :image
has_attached_file :image, styles: { medium: "320x240>"}
validates :description, presence: true
validates :user_id, presence: true
validates_attachment :image, presence: true,
content_type: { content_type: ["image/jpeg", "image/jpg", "image/gif", "image/png"] },
size: { in: 0..5.megabytes }
belongs_to :user
end
When I try to upload an image, my server lags for 3 minutes, console goes crazy and after those 3 minutes I get this error message - "has contents that are not what they are reported to be".
I just changed the model to this
class Pin < ActiveRecord::Base
attr_accessible :description, :image
has_attached_file :image, styles: { medium: "320x240>"}
validates :description, presence: true
validates :user_id, presence: true
validates_attachment :image, presence: true,
# content_type: { content_type: ["image/jpeg", "image/jpg", "image/gif", "image/png"] },
size: { in: 0..5.megabytes }
validates_attachment_content_type :image, :content_type => /\Aimage/
belongs_to :user
end

Undefined method on staging environment, works fine locally

Having some issues with my staging environment at the moment. I have my app on Heroku (both staging and production). It works perfectly on local, but when I push it to the staging environment I keep getting an undefined method for category_id.
I have reset the databases, run my migrations and put the seeds in to no avail. The only thing I can think is there is something wrong with my product model but I haven't changed that part of the app since I last pushed it to production (works fine with the current version on there).
Is there any chance that one of my migrations is not going through? That's the only thing I can think of.
Product model:
class Product < ActiveRecord::Base
belongs_to :subcategory
mount_uploader :product_image, ProductImageUploader
validates :title, :description, presence: true
validates :title, uniqueness: true
validates :image_url, allow_blank: true, format: { with: %r{\.(gif|jpg|png)\Z}i, message: 'must be a URL for GIF, JPG or PNG image.'}
validates :subcategory_id, presence: true
end
Products Controller:
class ProductsController < ApplicationController
skip_before_filter :authorize, only: [:show, :index]
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.order("title ASC")
#categories = Category.all
#subcategories = Subcategory.order("title ASC")
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
#product = Product.new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render json: #product, status: :created, location: #product }
else
format.html { render action: 'new' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { head :ok }
else
format.html { render action: 'edit' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :description, :image_url, :product_image, :subcategory_id, :category_id)
end
end
The view that is causing the error message:
=form_for(#product) do |f|
-if #product.errors.any?
#error_explanation
%h2
=pluralize(#product.errors.count, "error")
prohibited this product from being saved:
%ul
-#product.errors.full_messages.each do |msg|
%li
=msg
%br
.field
=f.label :title
%br
=f.text_field :title, size: 100
%br
.field
=f.label :description
%br
=f.text_area :description, cols: 100, rows: 10
%br
.field
=f.label :product_image
=f.file_field :product_image
.field
=f.label :category_id
%br
=f.collection_select(:category_id, Category.all, :id, :title)
%br
.field
=f.label :subcategory_id
%br
// =f.collection_select(:subcategory_id, Subcategory.all, :id, :title)
%select{:id => "product_subcategory_id", :name => "product[subcategory_id]", :disabled => "disabled"}
%option
Select a category first...
%br
.actions
%br
=f.submit
%br
%br
:javascript
$(document).ready(function(){
$("select#product_category_id").change(function(e) {
var val = $(this).val();
var subCatSelect = $("select#product_subcategory_id");
subCatSelect.empty();
subCatSelect.append("<option>Loading...</option>");
$.get("/subcategories.json?category="+val)
.done(function(response) {
subCatSelect.empty();
if (response.length > 0) {
$.each(response, function(k,v) {
subCatSelect.append("<option id='"+v.id+"'>"+v.title+"</option>");
subCatSelect.removeAttr("disabled");
});
} else {
subCatSelect.attr("disabled", "disabled");
subCatSelect.append("<option>No Subcategories</option>");
}
});
});
});
And the error message:
ActionView::Template::Error (undefined method `category_id' for #<Product:0x007f64ab47c1d0>):
30: .field
31: =f.label :category_id
32: %br
33: =f.collection_select(:category_id, Category.all, :id, :title)
app/views/products/_form.html.haml:33:in `block in _app_views_products__form_html_haml__3508934121535598535_70035173692040'
app/views/products/_form.html.haml:1:in `_app_views_products__form_html_haml__3508934121535598535_70035173692040'
app/views/products/new.html.haml:7:in `_app_views_products_new_html_haml__3953831312052620477_70035173605140'
It may be an issue with the naming conventions in your asset pipeline.
Try precompiling your asset pipeline befor pushing to Heroku:
bundle exec rake assets:precompile RAILS_ENV=production
git commit -a -m "Prempile assets for release"
git push
git push heroku master
Here's some more info from Heroku on this:
https://devcenter.heroku.com/articles/rails-asset-pipeline
Not sure if this will fix it, but it's very easy to try it. I've found that this fixes most of problems moving from development/test to production.
Hope this helps!
I'm not too sure what happened but when I cleared the heroku DB, re-ran my migrations and seeds it decided to work.... I have no idea what happened.

Resources