Sinatra + Paperclip : undefined method `descendants' - ruby

I'm currently converting a very small Rails application to Sinatra. This Rails app was relying on ActiveRecord + Paperclip + Amazon S3 for picture storage, and I have troubles making it work in Sinatra (but I believe it would be the same for any kind of Rack-based application), with ActiveRecord + Paperclip + Amazon S3 as well.
Here's what I have so far:
Gemfile:
gem 'paperclip'
gem 'paperclip-rack', require: 'paperclip/rack'
gem 'aws-sdk'
Model:
class Photo < ActiveRecord::Base
include Paperclip::Glue
has_attached_file :image,
:storage => :s3,
:s3_credentials => "config/s3.yml",
:bucket => 'mybucket',
:path => ':style/:photo_id.:extension',
:styles => {
:original => '1200x1200>',
:miniature => '80x80#',
:slideshow => 'x200'
}
end
View:
form method="post" action="/photos/add" enctype='multipart/form-data'
input type="file" name="image"
input#submit-button type="submit"
Route/Action:
post '/photos/add' do
photo = Photo.new
photo.image = params[:image]
#image[:tempfile] = params[:image][:tempfile],
#image[:filename] = params[:image][:filename],
#image[:content_type] = params[:image][:type],
#image[:size] = params[:image][:tempfile].size
photo.save
redirect "/"
end
And the error I'm getting when trying to upload something :
NoMethodError at /admin/photos/add
undefined method `descendants' for Paperclip::Validators::AttachmentFileNameValidator:Class
file: attachment.rb location: each line: 393
I've tried to play with the :image param in my route (and manually assign each value to the field that was created by paperclip, see the commented lines) but it didn't seem to work any better. Any idea guys ? I'm stuck and have no clue where to start to get this to work.
Note: I've removed all validations and stuff so I even don't understand the error message I'm getting.

I (think) I was able to monkey patch the #descendants method using this SO answer:
Look up all descendants of a class in Ruby
So I monkey-patched Paperclip in one of my initializers, which seemed okay to me since I don't care about validating the content type of the attachment:
module Paperclip
module Validators
class AttachmentFileNameValidator
def self.descendants
ObjectSpace.each_object(Class).select { |klass| klass < self }
end
end
class AttachmentContentTypeValidator
def self.descendants
ObjectSpace.each_object(Class).select { |klass| klass < self }
end
end
class AttachmentFileTypeIgnoranceValidator
def self.descendants
ObjectSpace.each_object(Class).select { |klass| klass < self }
end
end
end
end
I'm using Paperclip 4.2 and Sinatra 1.4.5

There is no official support for non-Rails apps using Paperclip. See a discussion on it here
You'll notice if you look in Paperclip::Validators::AttachmentFileNameValidator:Class you'll see:
class AttachmentFileNameValidator < ActiveModel::EachValidator
def initialize(options)
options[:allow_nil] = true unless options.has_key?(:allow_nil)
super
end
ActiveModel is bundled w/ rails, so I'm guessing it's blowing up on the inheritance in here. Either way, I'd move over to an uploader friendly to sinatra like carrierwave

Related

Why does respond_with JSON not work?

I'm having a problem when trying to use the return to in a rails controller. This is not working:
class UsersController < ApplicationController
respond_to :json
def create
#user = User.create params[:user_info]
respond_with #user
end
end
This works:
class UsersController < ApplicationController
respond_to :json
def create
#user = User.create params[:user_info]
respond_with #user do |format|
format.json { render json: #user.to_json }
end
end
end
Why? This is the error I have in the server's log when using the one that doesn't work:
NoMethodError (undefined method `user_url' for #<UsersController:0x007fd44d83ea90>):
app/controllers/users_controller.rb:7:in `create'
My route is:
resources :users, :only => [:create]
responds_with tries to redirect to user_url, so it looks for a show method in your user controller, which you don't have, since your route is limited to the create method only. Since the create method redirects to the show method by default this doesn't work. But in your second version you are actually rendering something, so no redirection happens.
You can give a :location option to respond_with if that's what you want, like so:
respond_with(#user, :location => home_url)
or use the render version as you do in your second version.

Undefined method `get' for #<RSpec::Core::ExampleGroup::Nested_1 displayed in Rspec Controllers

After running the following code from Rspec - Controllers, I get an error from the get method
it "assigns #MyItems" do
my_item = mock(:mypay_items)
my_item = mock( MyItem)
MyItem.should_receive(:all).and_return(my)
get 'index'
assigns[:my_items].should eql(my_items)
response.should be_success
end
It results in an error:
undefined method `get' for #<RSpec::Core::ExampleGroup::Nested_1:0x34b6ae0>
It would seem that you're not properly declaring your spec as a controller spec, which results in the HTTP request methods (get, post, etc.) not being available. Make sure that at the top of your spec, you have something like:
describe PostsController do
...
end
Replace PostsController with the name of your controller. If that doesn't work, add :type => :controller:
describe PostsController, :type => :controller do
...
end
See also this answer: undefined method `get' for #<RSpec::Core::ExampleGroup::Nested_1:0x00000106db51f8>
If at all you are using 'spec/features', you may need to add the following to your 'spec_helper.rb'
config.include RSpec::Rails::RequestExampleGroup, type: :feature
I had the same problem and the solution that worked for me was to add require 'rspec/rails' to my spec_helper file. All my controllers were setup correctly and adding the :type => controller didn't help.

How do you put dynamic content in an action mailer subject line?

I'm trying to put the name of my app in the subject line of emails that action mailer sends. I have no problem doing this with the default from email address, but when I try to add it to the subject it sends it through as plain text <%= app_name %>.
Here's my mailers/user_mailer.rb:
class UserMailer < ActionMailer::Base
add_template_helper(ApplicationHelper)
extend ApplicationHelper
default from: "#{app_name} <#{system_email}>"
def reset_password_email(user)
#user = user
#url = "#{root_url}/password_resets/#{user.reset_password_token}/edit"
mail(:to => user.email,
:subject => "Reset Your Password | #{app_name}")
end
end
And here's what I have in my application helper:
def app_name
'Tip Share'
end
def app_domain
'tipshare.herokuapp.com'
end
def system_email
'info#wingardcreative.com'
end
Neither #{app_name} or <%= app_name %> works. How do I do this?
Have you tried adding it like this:
include ApplicationHelper
By extending UserMailer with ApplicationHelper, those methods are available as class methods - which is why the reference in default from: "#{app_name} <#{system_email}>" works.
Within the reset_password_email method, app_name would be an undefined local variable.
So you either need to additionally include ApplicationHelper, or call it with self.class.app_name.

Paperclip not saving attachment on Padrino

I am building a site using padrino. I use paperclip for uploading logos to one of the models. The problem I am experiencing is that Paperclip does not save the attachment, but also does not throw any errors. I think that the parameters passed to the controller are of incorrect type, as the params[:logo] is a hash and should probably be a some kind of a file type? How can I make Paperclip save the attachments passed in the parameters?
The model:
class Charity < ActiveRecord::Base
include Paperclip::Glue
attr_accessible :name, :description, :logo
has_attached_file :logo, path: "/public/:attachment/:id/:basename.:extension"
end
The logo is set in the controller like so:
post :create do
#charity = Charity.new(params[:charity])
if #charity.save!
flash[:notice] = 'Charity was successfully created.'
redirect url(:charities, :edit, id: #charity.id)
else
render 'charities/new'
end
end
The form passing the parameters to the controller looks like this (parts omitted for brevity):
- form_for :charity, url(:charities, :create), multipart: true, class: :form do |f|
(...)
.group
==f.label :logo
==f.error_message_on :logo
==f.file_field :logo
(...)
I am using Paperclip 2.7.0 and Padrino 0.10.7.
I also have added this to boot.rb as per Using Paperclip with Padrino :
Padrino.before_load do
File.send(:include, Paperclip::Upfile)
Paperclip.options[:logger] = Padrino.logger
Paperclip.options[:command_path] = "/usr/local/bin"
ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, Paperclip::Schema)
ActiveRecord::ConnectionAdapters::Table.send(:include, Paperclip::Schema)
ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, Paperclip::Schema)
end
Mmm, I've no idea. Maybe this:
path: Padrino.root('/public/:attachment/:id/:basename.:extension')
Can you go in padrino console and try:
>> require 'open-uri'
>> puts Paperclip.default_options
>> c = Charity.create!
>> c.logo = open('http://1.bp.blogspot.com/-0Hn3AjTJj6U/TZHe3ragXGI/AAAAAAAAA1M/_SBk3dx61EE/s1600/med_funny-cat.jpg')
>> c.save!

paperclip and rails 3.1 NoMethodError and nil object

I just updated Rails 3.0.10 to 3.1 and everything seems to be ok.
But Paperclip don't work anymore and give me an error :
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]=
I'm unable to find the problem.. thank for help
[edit after comment]
Model :
class Community < ActiveRecord::Base
has_attached_file :commicon, :styles => { :thumb => "80x80>", :medium => "34x34!", :small => "20x20>", :rectangle => "80x40!", :mediumrect => "34x17>" , :smallrect => "20x10>"}
Controller:
class CommunitiesController < ApplicationController
def show
#community = Community.find(params[:id])
View :
<%= image_tag #community.commicon.url(:thumb) %>
I think nothing so special ?
I found my problem, thanks to the deprecated information of rails.
I updated my rails 3.1 to 3.2 and then it tell me that the plugins will be removed in the version 4.
After a quick look, I saw that I have a gem AND a plugin for paperclip and think my app was using the plugin.
Trashed the vendor folder and everything OK

Resources