PG::UndefinedTable: ERROR: relation "cities" does not exist LINE 8: WHERE a.attrelid = '"cities"'::regclass ^ - ruby

I am new to Sinatra and trying to create a post request which would add some data into "City" table in PGadmin. But, I am getting an error when trying to add it. The get request works fine, and posting static data on the post endpoint also works fine, but posting data doesn't I am not sure what's wrong since the migration and the model for city does exist. Here's the code:
city.rb
class City < UserDB
validates_presence_of :name, :pin
def as_json(options = {})
super({only: [:city, :pin]})
end
end
migration:
class CreateCity < ActiveRecord::Migration[6.0]
def change
create_table :city do |t|
t.string :name
t.integer :pin
end
end
end
module Users
module V1
class CityController< LocalAPI::ApplicationBase
before do
content_type 'application/json'
end
get '/' do
city=City.all
if city
"city exists"
else
"doesn't exist"
end
end
post '/add' do
params = JSON.parse request.body.read
#name= params['name']
#pin= params['pin']
#city=City.new(name:#name,pin:#pin)
if #city.save
return output(200, #city.as_json)
else
"cant create"
end
end
end
end
end
I am trying to post the below content through postman:
{
"name": "hamilton",
"pin":"222"
}
Please note that the route is configured and it does work when I visit the url. Also have ran db:migrate

Related

rollback transaction error rails from google geocoding api

I am trying to create a review form in my rails app but when i click on the submit button, the form cannot be submitted.When i lookup the error in the terminal and i get this error. i searched the error but couldn't find any solution. did anyone had this issue before?:
Google API error: over query limit.
(0.1ms) rollback transaction
Update
I am not only getting the Google API error. sometimes i get this error and other time i only get rollback transaction only.
This is the Reviews Controller:
class ReviewsController < ApplicationController
# check if logged in
before_action :check_login, except: [:index, :show]
def index
# this is our list page for our reviews
#price = params[:price]
#cuisine = params[:cuisine]
#location = params[:location]
# start with all the reviews
#reviews = Review.all
# filtering by price
if #price.present?
#reviews = #reviews.where(price: #price)
end
# filter by cuisine
if #cuisine.present?
#reviews = #reviews.where(cuisine: #cuisine)
end
# search near the location
if #location.present?
#reviews = #reviews.near(#location)
end
end
def new
# the form for adding a new review
#review = Review.new
end
def create
# take info from the form and add it to the model
#review = Review.new(form_params)
# and then associate it with a user
#review.user = #current_user
# we want to check if the model can be saved
# if it is, we're go the home page again
# if it isn't, show the new form
if #review.save
flash[:succces] = "Your review was posted!"
redirect_to root_path
else
# show the view for new.html.erb
render "new"
end
end
def show
# individual review page
#review = Review.find(params[:id])
end
def destroy
# find the individual review
#review = Review.find(params[:id])
# destroy if they have access
if #review.user == #current_user
#review.destroy
end
# redirect to the home page
redirect_to root_path
end
def edit
# find the individual review (to edit)
#review = Review.find(params[:id])
if #review.user != #current_user
redirect_to root_path
elsif #review.created_at < 4.hours.ago
redirect_to review_path(#review)
end
end
def update
# find the individual review
#review = Review.find(params[:id])
if #review.user != #current_user
redirect_to root_path
else
# update with the new info from the form
if #review.update(form_params)
# redirect somewhere new
redirect_to review_path(#review)
else
render "edit"
end
end
end
def form_params
params.require(:review).permit(:title, :restaurant, :body, :score,
:ambiance, :cuisine, :price, :address)
end
end
This is the Review form page:
<%= simple_form_for #review do |f| %>
<%= f.input :title %>
<%= f.input :restaurant %>
<%= f.input :address %>
<%= f.input :body %>
<%= f.input :cuisine %>
<%= f.input :price %>
<%= f.input :score %>
<%= f.input :ambiance %>
<%= f.button :submit %>
<% end %>
The Review Model
class Review < ApplicationRecord
# add an association that has a 1-to-many relationship
has_many :comments
has_many :bookmarks
# add an association to the user
belongs_to :user
geocoded_by :address
after_validation :geocode
validates :title, presence: true
validates :body, length: { minimum: 10 }
validates :score, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 10 }
validates :restaurant, presence: true
validates :address, presence: true
def to_param
id.to_s + "-" + title.parameterize
end
end
This is My Schema file
create_table "reviews", force: :cascade do |t|
t.string "title"
t.text "body"
t.integer "score"
t.string "restaurant"
t.integer "price"
t.string "cuisine"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "phone_number"
t.string "ambiance"
t.text "address"
t.float "latitude"
t.float "longitude"
t.integer "user_id"
end
You have two problems:
you are going over Google's Geocoding API quota as evidenced by the error message "over query limit"
Most likely because of that, your model cannot be saved is rolled back. The geocoding API call fails, it doesn't save.
I would check the Google API Console and see if you have actually hit their quota (possible if you're running multiple tests and you're on their free tier of service). If you have not hit the limit, file a support request with Google API.
You probably reached your Google API quota.
In model you have geocoded_by ... that is used by gem geocoder so have a look at that.
Google has per second limit as well as per day limit link

Testing with Postman keeps returning Invalid JSON error

I have created REST Api in Ruby on Sinatra platform. I am testing the service with Postman and whatever JSON form I try to POST I keep getting an error 400 Invalid JSON SUCKER. The error is defined on the back end in case of invalid JSON form. Please take a look at the back end and tell me what am I doing wrong.
I have to mention that GET method works with Postman and cURL from the command line while POST works only if I use it with cURL but NOT in POSTMAN.
#server.rb
require 'sinatra'
require 'mongoid'
require 'sinatra/namespace'
require 'sinatra/base'
#require 'json'
before do
content_type :json
headers 'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => ['OPTIONS', 'GET', 'POST', 'PATCH']
end
#load database config
Mongoid.load! "mongoid.config"
#Class Company
class Company
include Mongoid::Document
field :compid, type: String
field :name, type: String
field :address, type: String
field :city, type: String
# validates :compid, presence: true
# validates :name, presence: true
index({ compid:1 }, { unique: true, name: "compid_index" })
index({ name: 'text' })
scope :name, -> (name) { where(name: /^#{name}/) } # this could be changed to /^#{title}/i to make case insensitive searcg =end
scope :compid, -> (compid) { where(compid: compid) }
end
#Serializers
class Serializer
def initialize(company)
#company = company
end
def as_json(*)
data ={
id:#company.compid.to_s,
name:#company.name,
address:#company.address,
city:#company.city,
}
data[:errors] = #company.errors if#company.errors.any?
data
end
end
# Endpoints
get '/' do
'List of all Companies'
end
namespace '/api/v1' do
before do
content_type 'application/json'
end
helpers do
def base_url
#base_url ||= "#{request.env['rack.url_scheme']}://{request.env['HTTP_HOST']}"
end
def json_params
begin
JSON.parse(request.body.read)
rescue
halt 400, { message:'Invalid JSON' }.to_json
end
end
end
get '/companies' do
companies = Company.all
[ :name, :compid,].each do |filter|
companies = companies.send(filter, params[filter]) if params[filter]
end
#put it through the serializer not to get all te atributes
companies.map { |company| Serializer.new(company) }.to_json
end
get '/companies/:compid' do |compid| #get the details about the company by searching with compid
company = Company.where(compid: compid).first
halt(404, { message:'Company Not Found'}.to_json) unless company
Serializer.new(company).to_json
end
post '/companies' do
company = Company.new(json_params)
if company.save
response.headers['Location'] = "#{base_url}/api/v1/companies{company.copmid}" # "{company.id}"
status 201
else
status 422
body Serializer.new(company).to_json
end
end
The data that I GET with the Postman looks like this:
[{"id":"5a1271f7943e8a0f5fd76008","name":"The Power Of Habit","address":"Charles Duhigg Vej","city":"Viborg"}]
I have tried to POST data in various forms:
[{"id":"5a1271f79asdd76008","name":"The Power Of Habit","address":"Charles Duhigg Vej","city":"Viborg"}]
{"id":"5a1271f79asdd76008","name":"The Power Of Habit","address":"Charles Duhigg Vej","city":"Viborg"}
[{"compid":"5a1271f79asdd76008","name":"The Power Of Habit","address":"Charles Duhigg Vej","city":"Viborg"}]
{"compid":"5a1271f79asdd76008","name":"The Power Of Habit","address":"Charles Duhigg Vej","city":"Viborg"}

Rails Paperclip - Duplicating the attachment file name in another field

I've got the following table:
create_table "documents", force: true do |t|
t.string "title"
t.integer "subject_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "attachment_file_name"
t.string "attachment_content_type"
t.integer "attachment_file_size"
t.datetime "attachment_updated_at"
end
Whenever I upload a file (using Paperclip), I want to duplicate the param of 'attachment_file_name' to 'title'.
This app is an API, but I'm using a debugs_controller to test it.
DebugsController
class DebugsController < ApplicationController
def index
#document = Document.new
#documents = Document.all
#subject = Subject.new
end
end
debugs/index.html.erb
<form action="http://0.0.0.0:3000/documents" method="POST" enctype="multipart/form-data">
<input name="document[title]" type="text" placeholder="doc naam">
<input name='document[attachment]' type="file">
<input name="document[subject_id]" type="text" placeholder="Subject id">
<input type="submit">
</form>
DocumentsController
class DocumentsController < ApplicationController
before_action :set_document, only: [:show, :update, :destroy]
skip_before_action :verify_authenticity_token
respond_to :json
def index
#documents = Document.all
end
def new
#document = Document.new
#documents = Document.all
end
def show
end
def create
#document = Document.new(document_params)
#document.title = params[:attachment].original_filename
if #document.save
respond_with(#document, status: :created)
else
respond_with(#document, status: 403)
end
end
def update
if #document.update(document_params)
respond_with(#document)
else
respond_with(#document.errors, status: :unprocessable_entity)
end
end
def destroy
#document.destroy
respond_with(#document, status: :destroyed)
end
private
def set_document
#document = Document.find(params[:id])
end
def document_params
params.require(:document).permit(:title, :attachment, :subject_id)
end
end
Document.rb
class Document < ActiveRecord::Base
belongs_to :subject
has_many :notes
has_attached_file :attachment, url: '/system/:attachment/:id_partition/:basename.:extension'
validates_attachment :attachment, presence: {
message: 'You have to upload a file!' }, content_type: {
content_type: %w( application/pdf ), message: 'PDF files only.' }, size: {
in: 0..10.megabytes, message: 'The maximum file-size is 10MB.' }
validates :subject_id, presence: { message: 'Assign your document to a case!' }
end
This outputs 'undefined method `original_filename' for nil:NilClass' for me.
Params:
{"document"=>{"title"=>"",
"attachment"=>#<ActionDispatch::Http::UploadedFile:0x007fbcea87c518 #tempfile=#<Tempfile:/var/folders/sy/9v_t59x974qg_m2nvmcyvkjr0000gn/T/RackMultipart20141202-14285-z5aj46>,
#original_filename="Teamsweet.pdf",
#content_type="application/pdf",
#headers="Content-Disposition: form-data; name=\"document[attachment]\"; filename=\"Teamsweet.pdf\"\r\nContent-Type: application/pdf\r\n">,
"subject_id"=>"1"},
"format"=>:json}
Does anyone know how I can duplicate the contents of the 'attachment_file_name' to the 'title' field of Documents? Also; is it possible to remove the extention of the uploaded file in the process of duplicating the file name?
You can do that in the model instead of in the controller.
class Document < ActiveRecord::Base
before_save :set_title
def set_title
self.title = self.attachment_file_name
end
...
end

Rails 4 ActiveModel::MissingAttributeError in OrdersController#create

I m trying to build a shopping cart for a website. I have the cart working so you can add to the cart. The problem I am having is when I try and checkout items in the cart and try to submit my order. I am getting the following error:
ActiveModel::MissingAttributeError in OrdersController#create
along with
can't write unknown attribute `order_id'
The problem is highlighting this piece of code in my orders_controller.rb file
respond_to do |format|
if #order.save
Cart.destroy(session[:cart_id]) session[:cart_id] = nil
I just cant seem to fix this error.
Below is the create method in my orders_controller.rb file
def create
#order = Order.new(order_params)
#order.add_line_items_from_cart(#cart)
respond_to do |format|
if #order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
format.html { redirect_to store_url,
notice: 'Thank you for your order.' }
format.json { render action: 'show', status: :created, location: #order }
else
format.html { render action: 'new' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
my migration file
class AddOrderToLineItem < ActiveRecord::Migration
def change
add_column :line_items, :order, :reference
end
end
my order.rb model
class Order < ActiveRecord::Base
has_many :line_items, dependent: :destroy
validates :name, :address, :email, presence: true
PAYMENT_TYPES = [ "Check", "Credit card", "Purchase order" ]
validates :pay_type, inclusion: PAYMENT_TYPES
def add_line_items_from_cart(cart)
cart.line_items.each do |item|
item.cart_id = nil
line_items << item
end
end
end
migration order table
class CreateOrders < ActiveRecord::Migration
def change
create_table :orders do |t|
t.string :name
t.text :address
t.string :email
t.string :pay_type
t.timestamps
end
end
end
Ok, I think I see the problem. Your migration for orders in line items probably didn't create the order_id column you expected, it probably created an orders column or something.
Verify that this is the case in the database. If so, undo your previous migration and try this instead:
class AddOrderToLineItem < ActiveRecord::Migration
def change
add_column :line_items, :order_id, :int
end
end
If not, please respond to this answer.

When is the validator of email uniqueness trigerred?

I have a question about this test from the Michael Hartl tutorial :
Model:
class User < ActiveRecord::Base
.
.
.
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: true
end
Test:
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com")
end
.
.
.
describe "when email address is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
end
My understanding of the uniqueness validator for the email is that it cannot be added twice in the database. But in this test, the User is just instantiated with a new, not a create.
So here is what I think happens:
#user = User.new (just in memory)
...
user_with_same_email = #user.dup we have two users in memory
...
user_with_same_email.save we are inserting the first user in the db, so it should be valid, and yet the test it { should_not be_valid } passes.
What am I getting wrong ?
What really happens:
In before:
#user = User.new (just in memory)
In the describe:
user_with_same_email = #user.dup we have two users in memory
user_with_same_email.save we are inserting the first user in the db, so it should be valid, and it is ! But that's not what's being tested here
In the it:
should_not be_valid calls .valid? on #user, and since we've just inserted an user with the same email, #user is not valid. And so the test passes.

Resources