Rails Paperclip - Duplicating the attachment file name in another field - ruby

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

Related

Get Stripe charge information rails 5 create order

So I'm implementing Stripe and users are able to purchase successfully, however, I would like to get the charge information, last 4 card numbers, card type etc so I can generate receipts using https://github.com/excid3/receipts.
Here is what I have so far:
PaymentsController
class PaymentsController < ApplicationController
before_action :authenticate_user!
def create
token = params[:stripeToken]
#course = Course.find(params[:course_id])
#user = current_user
begin
charge = Stripe::Charge.create(
amount: (#course.price*100).to_i,
currency: "gbp",
source: token,
description: params[:stripeEmail],
receipt_email: params[:stripeEmail]
)
if charge.paid
Order.create(
course_id: #course.id,
user_id: #user.id,
Amount: #course.price
)
end
flash[:success] = "Your payment was processed successfully"
rescue Stripe::CardError => e
body = e.json_body
err = body[:error]
flash[:error] = "Unfortunately, there was an error processing your payment: #{err[:message]}"
end
redirect_to course_path(#course)
end
end
OrdersController
class OrdersController < ApplicationController
layout proc { user_signed_in? ? "dashboard" : "application" }
before_action :authenticate_user!
def index
#orders = Order.includes(:course).all
end
def show
#order = Order.find(params[:id])
respond_to do |format|
format.pdf {
send_data #order.receipt.render,
filename: "#{#order.created_at.strftime("%Y-%m-%d")}-aurameir-courses-receipt.pdf",
type: "application/pdf",
disposition: :inline
}
end
end
def create
end
def destroy
end
end
Order.rb
class Order < ApplicationRecord
belongs_to :course
belongs_to :user
validates :stripe_id, uniqueness: true
def receipt
Receipts::Receipt.new(
id: id,
subheading: "RECEIPT FOR CHARGE #%{id}",
product: "####",
company: {
name: "####",
address: "####",
email: "####",
logo: "####"
},
line_items: [
["Date", created_at.to_s],
["Account Billed", "#{user.full_name} (#{user.email})"],
["Product", "####"],
["Amount", "£#{amount / 100}.00"],
["Charged to", "#{card_type} (**** **** **** #{card_last4})"],
["Transaction ID", uuid]
],
font: {
normal: Rails.root.join('app/assets/fonts-converted/font-files/AvenirBook.ttf')
}
)
end
end
schema.rb
create_table "orders", force: :cascade do |t|
t.integer "user_id"
t.integer "course_id"
t.integer "stripe_id"
t.integer "amount"
t.string "card_last4"
t.string "card_type"
t.integer "card_exp_month"
t.integer "card_exp_year"
t.string "uuid"
t.index ["course_id"], name: "index_orders_on_course_id"
t.index ["user_id"], name: "index_orders_on_user_id"
end
How would I go about getting the charge information?
All the information you need is in the charge object you created.
if charge.paid
Order.create(
course_id: #course.id,
user_id: #user.id,
amount: #course.price,
card_last4: charge.source.last4,
card_type: charge.source.brand,
card_exp_month: charge.source.exp_month,
card_exp_year: charge.source.exp_year
)
end
See https://stripe.com/docs/api/ruby#charge_object for all the information available to you about a charge.
I guess you are not storing the Stripe Charge ID anywhere on successful payment.
My suggestion, store the charge ID in your Order record
if charge.paid
Order.create(
course_id: #course.id,
user_id: #user.id,
amount: #course.price,
stripe_charge_id: charge.id
)
end
In your receipt method you can fetch the stripe charge as follows:
def receipt
stripe_charge = Stripe::Charge.retrieve(stripe_charge_id)
...
end
The stripe_charge objects contains all the information and you can use whatever data you need.
Hope this helped.

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

undefined method `following' for nil:NilClass

I am working on a project similar to a twitter clone. However, I am running into an error that is the following: undefined method `following' for nil:NilClass in my controller. So, to start, here is my controller:
class EpicenterController < ApplicationController
def feed
#Here we initialize the array that will hold tweets from the current_user's
following list.
#following_tweets = []
Tweet.all.each do |tweet|
if current_user.following.include?(tweet.user_id)
#following_tweets.push(tweet)
end
end
end
def show_user
#user = User.find(params[:id])
end
def now_following
#user = User.find(params[:follow_id])
#Adding the user.id of the user you want to follow to your 'follow' array
attribute
current_user.following.push(params[:follow_id].to_i)
current_user.save
end
def unfollow
end
end
Here is my model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
serialize :following, Array
has_many :tweets
validates :username, presence: true, uniqueness: true
end
My Schema:
ActiveRecord::Schema.define(version: 20160811164903) do
create_table "tweets", force: :cascade do |t|
t.string "message"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
t.string "username"
t.text "bio"
t.string "location"
t.text "following"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name:
"index_users_on_reset_password_token", unique: true
end
Finally my application controller:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :username,
:bio,
:location, :following])
devise_parameter_sanitizer.permit(:account_update, keys: [:name,
:username, :bio, :location, :following])
end
end
Thank you for any help that may be provided. Please let me know if you need to see something else and I will add it.
Stack Trace:
NoMethodError (undefined method `following' for nil:NilClass):
app/controllers/epicenter_controller.rb:8:in `block in feed'
app/controllers/epicenter_controller.rb:7:in `feed'
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/actionpack-
4.2.6/lib/action_dispatch/middleware/templates/rescues/_source.erb (3.9ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/actionpack-
4.2.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
(2.7ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/actionpack-
4.2.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.9ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/actionpack-
4.2.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb
within rescues/layout (63.4ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/web-console-
2.3.0/lib/web_console/templates/_markup.html.erb (0.4ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/web-console-
2.3.0/lib/web_console/templates/_inner_console_markup.html.erb within
layouts/inlined_string (0.3ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/web-console-
2.3.0/lib/web_console/templates/_prompt_box_markup.html.erb within
layouts/inlined_string (0.3ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/web-console-
2.3.0/lib/web_console/templates/style.css.erb within layouts/inlined_string
(0.5ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/web-console-
2.3.0/lib/web_console/templates/console.js.erb within layouts/javascript
(62.0ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/web-console-
2.3.0/lib/web_console/templates/main.js.erb within layouts/javascript
(0.3ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/web-console-
2.3.0/lib/web_console/templates/error_page.js.erb within layouts/javascript
(0.6ms)
Rendered /Users/mikecuddy/.rvm/rubies/ruby-
2.2.1/lib/ruby/gems/2.2.0/gems/web-console-
2.3.0/lib/web_console/templates/index.html.erb (139.5ms)
current_user is nil for not logged in users, so you'll need to handle it:
if user_signed_in?
current_user.following # ...
else
store_location_for :user, request.path
redirect_to new_user_session_path, alert: 'You need to be logged in to do that.'
end
or
class EpicenterController < ApplicationController
before_action :authenticate_user! #, only: [:feed, :now_following] (optional)
# ...
end
if your controller is mostly intended for signed in users (which seems like it).

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.

Nested Attributes for Mongoid has_one relationship

I am trying to create a contact which is a has_one relation to a client. I am doing this with nested attributes. I am properly building the contact within the "new" view/controller. When I go to save the contact it is telling me the contact must be present. So for some reason it is not creating the contact.
ERROR:
Validation failed - Contact can't be blank.
Params:
{
"utf8"=>"✓",
"authenticity_token"=>"ep6es356WY5dja7D7C5Kj8Qc0Yvuh3IN2Z1iGG08J7c=",
"client"=>{
"contact_attributes"=>{
"first_name"=>"Scott",
"last_name"=>"Baute"
},
"commit"=>"Create Client"
}
Models:
class Client
include Mongoid::Document
include Mongoid::Timestamps
attr_accessible :role, :contact_id, :contact_attributes
# Relationships
belongs_to :firm, validate: true
has_one :contact, validate: true, autosave: true
# Matters is custom relationship
has_many :client_roles
# Nested Attr
accepts_nested_attributes_for :contact
validates :contact_id, presence: true
# Fields
field :contact_id
field :test
end
class Contact
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::MultiParameterAttributes
#Relationships
belongs_to :client
field :first_name
field :last_name
end
Controller:
# GET /clients/new
# GET /clients/new.json
def new
#client = current_firm.clients.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #client }
end
end
# POST /clients
# POST /clients.json
def create
#client = current_firm.clients.new(params[:client])
respond_to do |format|
if #client.save!
format.html { redirect_to client_path(#client.contact.id), notice: 'Client was successfully created.' }
format.json { render json: #client, status: :created, location: #client }
else
format.html { render action: "new" }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
View:
- #client.build_contact unless #client_contact
= semantic_form_for #client, html: { class: "form-horizontal"} do |f|
.control-group
= render "contact_fields", f: builder
.form-actions
= f.submit class: "btn btn-primary"
I think you need delete your reference to contact_id in your Client model. The has_one association do the foreign_key in your contact. Not in your client. So when you create a contact from client, only a client_id is define in your contact no contact_id in your client.
So delete line :
validates :contact_id, presence: true
# Fields
field :contact_id
in your Client model.

Resources