I want to save the full url of my uploaded images in a rails app using the CarrierWave gem. I update the entry just after the create action but it does not work. However, when I puts my variable, the full url appears but it only saves the identifier...
The Card controller, after_action method:
class CardsController < ApplicationController
before_action :set_card, only: [:show, :edit, :update, :destroy]
after_action :save_full_image_url, only: [:create, :update]
include Shortener
require 'carrierwave/orm/activerecord'
def save_full_image_url
c = #card
puts "URL: "+c.image_url.url
#card.update(image_url: c.image_url.url)
Rails.logger.info(#card.errors.inspect)
end
My Card model:
class Card < ApplicationRecord
validates :cta_button_url, :format => URI::regexp(%w(http https)), presence: { message: '%{value} : please enter valid url' }
validates :title, :subtitle, :cta_button_text, :cta_button_url, :presence => true
mount_uploader :image_url, ImageUploader
has_one :short_url
end
My full logs:
SQL (0.3ms) INSERT INTO "cards" ("letter_id", "title", "subtitle",
"image_url", "cta_button_text", "cta_button_url", "share_button")
VALUES (?, ?, ?, ?, ?, ?, ?) [["letter_id", 49], ["title",
"fsddssd"], ["subtitle", "fsdfsdfsd"], ["image_url", "10298593.jpg"],
["cta_button_text", "Visit site"], ["cta_button_url",
"http://www.testurl.com"], ["share_button", "t"]] (1.1ms) commit
transaction (0.1ms) begin transaction Card Load (0.2ms) SELECT
"cards".* FROM "cards" WHERE "cards"."id" = ? LIMIT ? [["id", 44],
["LIMIT", 1]] SQL (0.4ms) INSERT INTO "short_urls" ("card_id",
"token", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["card_id",
44], ["token", "PmK5vnuCU9Dczz995fz8Ddbf"], ["created_at", "2017-08-08
21:08:57.625325"], ["updated_at", "2017-08-08 21:08:57.625325"]]
(0.8ms) commit transaction Letter Load (0.2ms) SELECT "letters".*
FROM "letters" WHERE "letters"."id" = ? LIMIT ? [["id", 49],
["LIMIT", 1]] (0.1ms) begin transaction CoreBot Load (0.2ms)
SELECT "core_bots".* FROM "core_bots" WHERE "core_bots"."id" = ?
LIMIT ? [["id", 1], ["LIMIT", 1]] (0.1ms) commit transaction
Redirected to http://localhost:3000/dashboard/test URL:
http://localhost:3000/uploads/card/image_url/44/10298593.jpg
(0.1ms) begin transaction SQL (0.4ms) UPDATE "cards" SET
"image_url" = ? WHERE "cards"."id" = ? [["image_url",
"10298593.jpg"], ["id", 44]] (2.5ms) commit transaction
"10298593.jpg", cta_button_text: "Visit site", cta_button_url:
"http://www.testurl.com", share_button: true>, #messages={},
#details={}> Completed 302 Found in 60ms (ActiveRecord: 7.2ms)
When I log in the console "c.image_url.url" I get the full URL (http://localhost:3000/uploads/card/image_url/44/10298593.jpg) but when I update my entry, it only saves the end (10298593.jpg).
Any idea why I am not able to save the entire url even if I can get it in a variable before?
Problem solved! The issue was from the mount_uploader :image_url, ImageUploader
I created a "remote_image_url" and updated it with the full url. Now it works!
Related
I'm trying to test my track_controller's index method and it keeps returning a <500 Internal Server Error>.
A track is created by a user is associated with said user. So #track.user.name should return the user's name. Yet the error is indicating that the user returns nil despite me explicitly assigning the user, what gives?
Test log:
-------------------------------------------
TracksControllerTest: test_should_get_index
-------------------------------------------
[1m[36mUser Load (0.3ms)[0m [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?[0m [["id", 701806347], ["LIMIT", 1]]
[1m[36mTrack Load (0.1ms)[0m [1m[34mSELECT "tracks".* FROM "tracks" WHERE "tracks"."id" = ? LIMIT ?[0m [["id", 980190962], ["LIMIT", 1]]
[1m[35m (0.1ms)[0m [1m[35mSAVEPOINT active_record_1[0m
[1m[36mTrack Update (0.3ms)[0m [1m[33mUPDATE "tracks" SET "user_id" = ?, "updated_at" = ? WHERE "tracks"."id" = ?[0m [["user_id", 701806347], ["updated_at", "2018-12-11 14:30:49.753966"], ["id", 980190962]]
[1m[35m (0.1ms)[0m [1m[35mRELEASE SAVEPOINT active_record_1[0m
Started GET "/" for 127.0.0.1 at 2018-12-11 14:30:49 +0000
Processing by TracksController#index as HTML
[1m[35m (0.1ms)[0m [1m[35mSAVEPOINT active_record_1[0m
[1m[36mCart Create (0.2ms)[0m [1m[32mINSERT INTO "carts" ("created_at", "updated_at") VALUES (?, ?)[0m [["created_at", "2018-12-11 14:30:49.856142"], ["updated_at", "2018-12-11 14:30:49.856142"]]
[1m[35m (0.0ms)[0m [1m[35mRELEASE SAVEPOINT active_record_1[0m
Rendering tracks/index.html.haml within layouts/application
[1m[36mTrack Load (0.2ms)[0m [1m[34mSELECT "tracks".* FROM "tracks" ORDER BY created_at desc[0m
Rendered tracks/index.html.haml within layouts/application (23.1ms)
Completed 500 Internal Server Error in 51ms (ActiveRecord: 0.5ms)
NoMethodError - undefined method `name' for nil:NilClass:
app/views/tracks/index.html.haml:20:in `block in _app_views_tracks_index_html_haml___68907435507065187_70307785248520'
app/views/tracks/index.html.haml:8:in `_app_views_tracks_index_html_haml___68907435507065187_70307785248520'
test/controllers/tracks_controller_test.rb:17:in `block in <class:TracksControllerTest>'
tracks_controller_test.rb:
require 'test_helper'
include Warden::Test::Helpers
class TracksControllerTest < ActionDispatch::IntegrationTest
setup do
#user = users(:cscades)
login_as(#user)
#track = tracks(:one) #need to sign in the users in order for tracks to be deleted as only track creators can delete them
#track.user = #user
#track.save!
end
test "should get index" do
get root_path # root path == tracks#index
assert_response :success
end
track_controller.rb:
class TracksController < ApplicationController
skip_before_action :authenticate_user!, raise: false
before_action :set_track, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
# GET /tracks
# GET /tracks.json
def index
#tracks = Track.all.order("created_at desc")
end
index.html.haml (for tracks) error occurs on line indicated below:
- content_for :header do
%section.hero.is-warning
.hero-body
.container
%h1.title
Browse the newest Tracks
.track-index-grid.pt4
- #tracks.each do |track|
.track.border-light
.track-thumb
-unless track.image_url(:thumb).nil?
=link_to image_tag(track.image_url(:thumb)), track
- if track.genre
.condition
%span.tag.is-dark
= track.genre
.pa3
%h3.fw7.f4.title= link_to track.name, track
%p.has-text-gray.fw7.pt9
Sold by #{link_to track.user.name, new_message_path(:recipient => track.user.email), :title => "Send an email to #{track.user.name}"} #ERROR OCCURS HERE
%p.has-text-grey
#{track.description}
%p.f3.fw6.has-text-right.pt2.price= number_to_currency(track.price)
- if track_artist(track)
= link_to 'Edit', edit_track_path(track), class: "button is-small"
= link_to 'Delete', track, method: :delete, data: { confirm: "Are you sure ?" }, class: "button is-small"
users.yml (user fixtures):
cscades:
name: Cscades
encrypted_password: <%= Devise::Encryptor.digest(User,'password') %>
email: cscadesbooking#gmail.com
# column: value
#
polocardigan:
name: PoloCardigan
encrypted_password: <%= Devise::Encryptor.digest(User,'password') %>
email: cardiganbooking#gmail.com
# column: value
So I'm learning more about belongs_to and has_many Associations in Rails and am combining it with ActiveAdmin.
I have created a Model "Semester" and a Model "Field". A Semester has many Fields and a Field belongs to Semester.
My field Class looks like this:
class Field < ApplicationRecord
belongs_to :semester
accepts_nested_attributes_for :semester, allow_destroy: true
end
and my Semester class looks like this:
class Semester < ApplicationRecord
has_many :fields
accepts_nested_attributes_for :fields, allow_destroy: true
end
Now I registered the Models with active admin with the following two files:
ActiveAdmin.register Field do
permit_params :name, semesters_attributes: [:name]
end
and
ActiveAdmin.register Semester do
permit_params :name, :fields, fields_attributes: [ :field_id, :name]
end
And now there are two issues that come up upon proceeding that I absolutely can not ged rid off:
1) If I do not add optional: true after belongs_to :semester I will get an error message "must exist" upon trying to create a new Field with a respective Semester.
2) If I do add optional: true after belongs_to :semester I will be able to create a new Field but the "Semester" will just be "EMPTY" in the new field.
The console output of case 2) will look like this:
Started POST "/admin/fields" for 127.0.0.1 at 2018-08-17 15:23:54 +0200
Processing by Admin::FieldsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"+GPjjNPOv9GsjXnEtEjBcC0xUMHKKC+YpFLfiUFUOgsgBJ+pLCucscrN0YaTk551GFp4K5lBEI2RW1clw2vCWw==", "field"=>{"semester_id"=>"2", "name"=>"MAVT"}, "commit"=>"Create Field"}
AdminUser Load (0.1ms) SELECT "admin_users".* FROM "admin_users" WHERE "admin_users"."id" = ? ORDER BY "admin_users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ /home/divepit/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
Unpermitted parameter: :semester_id
(0.0ms) begin transaction
↳ /home/divepit/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
Field Create (0.6ms) INSERT INTO "fields" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "MAVT"], ["created_at", "2018-08-17 13:23:54.026418"], ["updated_at", "2018-08-17 13:23:54.026418"]]
↳ /home/divepit/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
(12.2ms) commit transaction
↳ /home/divepit/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
Redirected to http://0.0.0.0:3000/admin/fields/22
Completed 302 Found in 22ms (ActiveRecord: 13.0ms)
Started GET "/admin/fields/22" for 127.0.0.1 at 2018-08-17 15:23:54 +0200
Processing by Admin::FieldsController#show as HTML
Parameters: {"id"=>"22"}
AdminUser Load (0.2ms) SELECT "admin_users".* FROM "admin_users" WHERE "admin_users"."id" = ? ORDER BY "admin_users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ /home/divepit/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
Field Load (0.1ms) SELECT "fields".* FROM "fields" WHERE "fields"."id" = ? LIMIT ? [["id", 22], ["LIMIT", 1]]
↳ /home/divepit/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
Rendering /home/divepit/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activeadmin-1.3.1/app/views/active_admin/resource/show.html.arb
(0.1ms) SELECT COUNT(*) FROM "active_admin_comments" WHERE "active_admin_comments"."resource_type" = ? AND "active_admin_comments"."resource_id" = ? AND "active_admin_comments"."namespace" = ? [["resource_type", "Field"], ["resource_id", 22], ["namespace", "admin"]]
↳ /home/divepit/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
ActiveAdmin::Comment Exists (0.1ms) SELECT 1 AS one FROM "active_admin_comments" WHERE "active_admin_comments"."resource_type" = ? AND "active_admin_comments"."resource_id" = ? AND "active_admin_comments"."namespace" = ? LIMIT ? OFFSET ? [["resource_type", "Field"], ["resource_id", 22], ["namespace", "admin"], ["LIMIT", 1], ["OFFSET", 0]]
↳ /home/divepit/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
Rendered /home/divepit/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activeadmin-1.3.1/app/views/active_admin/resource/show.html.arb (73.4ms)
Completed 200 OK in 77ms (Views: 74.9ms | ActiveRecord: 0.5ms)
Thanks in advance for any tips on how to solve this! :)
First things first. Your associations are correct, but as per your associations you should not have field_id in semester table. Instead you should have semester_id in fields table. Also you should change semesters_attributes to semester_attributes
Unpermitted parameter: :semester_id
You should permit semester_id in the fields_attributes
fields_attributes: [ :semester_id, :name]
And finally in Rails 5, whenever a belongs_to association is defined, it is required to have the associated record present by default. To avoid this default behavior, you need to add optional: true
I have a four-level deep model structure: Domain > Subject > Device > Property
class Domain < ApplicationRecord
has_many :subjects
end
class Subject < ApplicationRecord
has_many :devices
belongs_to: :domain
end
class Device < ApplicationRecord
has_many :properties
belongs_to: :subject
end
class Property < ApplicationRecord
belongs_to :device
end
controller code
def update
result = #subject.update(parameters)
if result
render json: #subject
else
render_errors(#subject.errors)
end
end
#subject is retrieved as a before action, by querying the model tree from domain onwards, using domain_id and id parameters for domain and subject respectively. parameters is simply a hash of parameters, e.g. {name: :new_name}
When updating a Subject, the relation to domain is lost, i.e. domain_id is set to NUL by rails. The entire model tree below subject will also be disconnected from the parent domain as a result.
When removing has_many: :devices from the Subject model, everything works as expected. I just want to update a subject and preserve the relation to the parent domain. How would I achieve this with the model described above?
EDIT 1 - Added log of both situations.
Log with full relational model (that results in the bug)
Domain Load (0.5ms) SELECT "domains".* FROM "domains" WHERE "domains"."name" = ? LIMIT ? [["name", "Manatree"], ["LIMIT", 1]]
CACHE (0.0ms) SELECT "domains".* FROM "domains" WHERE "domains"."name" = ? LIMIT ? [["name", "Manatree"], ["LIMIT", 1]]
Subject Load (0.0ms) SELECT "subjects".* FROM "subjects" WHERE "subjects"."domain_id" = ? AND "subjects"."name" = ? LIMIT ? [["domain_id", 3], ["name", "s1"], ["LIMIT", 1]]
Subject Load (0.5ms) SELECT "subjects".* FROM "subjects" WHERE "subjects"."id" = ? LIMIT ? [["id", 5], ["LIMIT", 1]]
(0.0ms) begin transaction
Domain Load (0.0ms) SELECT "domains".* FROM "domains" WHERE "domains"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
SQL (7.1ms) UPDATE "subjects" SET "domain_id" = NULL WHERE "subjects"."domain_id" = ? AND "subjects"."id" = 5 [["domain_id", 3]]
Subject Exists (0.0ms) SELECT 1 AS one FROM "subjects" WHERE "subjects"."domain_id" = ? AND "subjects"."name" = ? LIMIT ? [["domain_id", 3], ["name", "s2"], ["LIMIT", 1]]
SQL (1.0ms) UPDATE "subjects" SET "name" = ?, "updated_at" = ? WHERE "subjects"."id" = ? [["name", "s2"], ["updated_at", "2017-07-31 08:46:38.171240"], ["id", 5]]
(7.5ms) commit transaction
Subject Load (0.0ms) SELECT "subjects".* FROM "subjects"
Completed 200 OK in 30ms (Views: 0.5ms | ActiveRecord: 16.6ms)
Log when removing belongs_to: :devices from Subject model
Domain Load (0.0ms) SELECT "domains".* FROM "domains" WHERE "domains"."name" = ? LIMIT ? [["name", "Manatree"], ["LIMIT", 1]]
CACHE (0.0ms) SELECT "domains".* FROM "domains" WHERE "domains"."name" = ? LIMIT ? [["name", "Manatree"], ["LIMIT", 1]]
Subject Load (0.5ms) SELECT "subjects".* FROM "subjects" WHERE "subjects"."domain_id" = ? AND "subjects"."name" = ? LIMIT ? [["domain_id", 3], ["name", "s3"], ["LIMIT", 1]]
Subject Load (0.5ms) SELECT "subjects".* FROM "subjects" WHERE "subjects"."id" = ? LIMIT ? [["id", 6], ["LIMIT", 1]]
(0.0ms) begin transaction
Domain Load (0.5ms) SELECT "domains".* FROM "domains" WHERE "domains"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
SQL (6.5ms) UPDATE "subjects" SET "name" = ?, "updated_at" = ? WHERE "subjects"."id" = ? [["name", "s4"], ["updated_at", "2017-07-31 08:48:57.962218"], ["id", 6]]
(7.0ms) commit transaction
Subject Load (0.0ms) SELECT "subjects".* FROM "subjects"
Completed 200 OK in 25ms (Views: 0.4ms | ActiveRecord: 15.1ms)
Edit 2 - There might be something wrong with the seed data...
domainA = Domain.create(name: :company)
s1 = domainA.subjects.create(name: :subject)
# domainA.save
d1 = s1.devices.create(name: :device)
# s1.save
p1 = d1.properties.create(name: :prop1, property_type: :double, value: 10.0)
p2 = d1.properties.create(name: :prop2, property_type: :string, value: :on)
p3 = d1.properties.create(name: :prop3, property_type: :string, value: :Lamp)
# d1.save
domainA.save
When removing has_many: :devices from the Subject model, everything
works as expected.
Going on with your models, Your Device model is flawed. You have belongs_to :device inside Device. Perhaps you should have belongs_to :subject as per the associations. This could have lead to your current problem. Try changing the Device model like so
class Device < ApplicationRecord
has_many :properties
belongs_to: :subject
end
I am using CarrierWave gem to upload images. I accept any size, but when uploaded, it must be resized server side. Im using this code to do this:
class PictureUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
process resize_and_pad: [1280, 720]
# other things
end
But when I'm clicking submit on form, it simply redirects me to index of controller.
If I change resize_and_pad to any other resize such as resize_to_fit, resize_to_fill or resize_to_limit, nothing changes.
If I comment line with resize thing, all works fine except image doesn't resize of course.
In logs I see this when I have resize thing:
(0.0ms) begin transaction
(0.0ms) commit transaction
(0.0ms) begin transaction
(0.0ms) rollback transaction
And without it:
(0.0ms) begin transaction
SQL (1.0ms) INSERT INTO "pictures" ("user_id", "name", "description", "created_at", "updated_at", "file")
VALUES (?, ?, ?, ?, ?, ?)
[["user_id", 1], ["name", "aaaaaaaaa"], ["description", "sssssssssssss"], ["created_at", 2016-10-01 19:37:49 UTC], ["updated_at", 2016-10-01 19:37:49 UTC], ["file", "3fe28255-f698-4f82-a64a-b41a90bb92a8.jpg"]]
(125.9ms) commit transaction
(0.0ms) begin transaction
(0.0ms) commit transaction
Rails 4.2.6
routes:
scope module: 'v1', defaults: { format: :json } do
resources :blog_posts, except: [:new, :edit] do
resources :comments, only: :create
end
end
Comments controller:
class V1::CommentsController < ApplicationController
before_action :set_blog_post
def create
comment = #blog_post.comments.new(comments_params)
comment.user = current_user
comment.save
respond_with(comment)
end
end
Why respond_with method didn't respond with comment object?
Logs:
Started POST "/blog_posts/1/comments" for ::1 at 2016-04-17 23:26:43 +0600
ActiveRecord::SchemaMigration Load (0.6ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by V1::CommentsController#create as JSON
Parameters: {"comment"=>{"message"=>"foobar"}, "blog_post_id"=>"1"}
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1 [["email", "test#test.com"]]
(0.1ms) begin transaction
SQL (0.4ms) UPDATE "users" SET "current_sign_in_at" = ?, "sign_in_count" = ?, "updated_at" = ? WHERE "users"."id" = ? [["current_sign_in_at", "2016-04-17 17:26:44.221258"], ["sign_in_count", 2], ["updated_at", "2016-04-17 17:26:44.222139"], ["id", 1]]
(0.7ms) commit transaction
BlogPost Load (0.4ms) SELECT "blog_posts".* FROM "blog_posts" WHERE "blog_posts"."id" = ? LIMIT 1 [["id", 1]]
(0.1ms) begin transaction
SQL (1.5ms) INSERT INTO "comments" ("message", "blog_post_id", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["message", "foobar"], ["blog_post_id", 1], ["user_id", 1], ["created_at", "2016-04-17 17:26:44.259405"], ["updated_at", "2016-04-17 17:26:44.259405"]]
(0.7ms) commit transaction
Completed 500 Internal Server Error in 102ms (ActiveRecord: 5.5ms)
NoMethodError (undefined method `comment_url' for #<V1::CommentsController:0x007f85ec9a98d0>):
app/controllers/v1/comments_controller.rb:9:in `create'
I have the same respond_with with blog_post in V1::BlogPostController and I got a response without errors.
As a workaround I have used render json: comment
NoMethodError (undefined method `comment_url' for V1::CommentsController:0x007f85ec9a98d0
Your comments are nested inside blog_posts, so respond_with(comment) doesn't work. Instead you need to use
respond_with(#blog_post, comment)
or
respond_with comment, location: blog_post_comment_path(#blog_post, comment)