I am just trying to do some really simple picture uploading using paperclip. I googled this issue and it seems like everyone else has much more complicated problem than simple uploads. Below are my models and controllers.
pin.rb
class Pin < ActiveRecord::Base
belongs_to :user
has_attached_file :image
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
# validates the description
validates :description, presence: true
validates :user_id, presence: true
# validates paperclip
validates_attachment :image, presence: true,
content_type: { content_type: ["image/jpeg", "image/jpg", "image/png", "image/gif"]},
size: { less_than: 5.megabytes }
end
pin_controller.rb
class PinsController < ApplicationController
#before_filer will authentiate users to make sure they are logged in before doing anything with the Pins, with the except of indexing the pins so non-logged on users can also see them
before_filter :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
# associate #pin to the current user's id
#pin = current_user.pins.new
end
# GET /pins/1/edit
def edit
# makes sure no other user can mess without a proper user id
#pin = current_user.pins.find(params[:id])
end
# POST /pins
# POST /pins.json
def create
# associate #pin to current user's id
#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 action: 'show', status: :created, location: #pin }
else
format.html { render action: 'new' }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /pins/1
# PATCH/PUT /pins/1.json
def update
# makes sure no other user can mess without a proper user id
#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 { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
# DELETE /pins/1
# DELETE /pins/1.json
def destroy
# makes sure no other user can mess without a proper user id
#pin = current_user.pins.find(params[:id])
#pin.destroy
respond_to do |format|
format.html { redirect_to pins_url }
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
Here are what I think might be wrong with my code.
First, I followed the One Month Rails Tutorial, but since I am watching the outdated Rails 3 series, I have to convert everything he teaches into Rails 4 by myself through research. I may have set up the strong parameters wrong in my pin.rb controller. I added :image attribute field to the pin_params method like so
params.require(:pin).permit(:description, :image)
is this the right way to add :image using strong parameters? In rails 3, he added :image within attr_accessible
Second, in the README for paperclip, it says I should run which convert and ultimately input this line in my config file
Paperclip.options[:command_path] = "/usr/local/bin/"
Since I am using a windows machine, this is what I got ultimately after looking answers for hours
Paperclip.options[:command_path] = "C:/Program Files/ImageMagick-6.8.9-Q16/"
does the above path looks relatively correct for windows?
I too use Windows and was getting this error. I found my answer here. From what I gather, Paperclip protects against spoofing by getting the server's OS to validate the file's MIME type. It does this by executing the following command:
file -b --mime <my_file_name.extension>
The trouble is, the standard Windows Command Line doesn't have the file command, so the spoofing check fails and Paperclip throws the error that you observed.
To resolve this issue:
Install File for Windows.
Edit your system's PATH variable so that it includes the "File for Windows" bin directory path. (For me, it was C:\Program Files (x86)\GnuWin32\bin.)
Restart your Command Line, Git Bash, or what have you because you edited your PATH variable.
Confirm that Windows Command Line now responds to the file command.
This method worked for me on Windows 8.1 with Paperclip 4.2.1.
In your pin.rb Delete this line
validates_attachment :image, presence: true,
content_type: { content_type: ["image/jpeg", "image/jpg", "image/png", "image/gif"]},
size: { less_than: 5.megabytes }
Because your already use
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
I also do One More Rails with the outdated videos,like you.
Check for errors from my project
Here is the link My GigHub Project Files
Good Luck!)
Related
notes use rails 5.2 and postgresql
I have Foluser model contains name,email,password,id_watch
I need when admin add new foluser
generate password
when admin create new foluser generate password like Secure Password Generator
get id_watch from admin model and put it to id_watch from Foluser model
Adminwhen register enterusername,email,password,id_watch`
in point 2 need take this id_watch and save it in user model .
admin only create foluser
`
class FolusersController < ApplicationController
before_action :set_foluser, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show, :new , :create, :edit]
# GET /folusers
# GET /folusers.json
def index
#folusers = current_master.foluser.all
#render json: #folusers
end
# GET /folusers/1
# GET /folusers/1.json
def show
##folusers = Foluser.where(master_id: #master.id).order("created_at DESC")
##foluser = Foluser.find(params[:id])
#render json: #foluser
end
# GET /folusers/new
def new
#foluser = current_master.foluser.build
end
# GET /folusers/1/edit
def edit
#render json: #foluser
end
# POST /folusers
# POST /folusers.json
def create
#foluser = current_master.foluser.build(foluser_params)
respond_to do |format|
if #foluser.save
format.html { redirect_to #foluser, notice: 'Foluser was successfully created.' }
format.json { render :show, status: :created, location: #foluser }
else
format.html { render :new }
format.json { render json: #foluser.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /folusers/1
# PATCH/PUT /folusers/1.json
def update
respond_to do |format|
if #foluser.update(foluser_params)
format.html { redirect_to #foluser, notice: 'Foluser was successfully updated.' }
format.json { render :show, status: :ok, location: #foluser }
else
format.html { render :edit }
format.json { render json: #foluser.errors, status: :unprocessable_entity }
end
end
end
# DELETE /folusers/1
# DELETE /folusers/1.json
def destroy
#foluser.destroy
respond_to do |format|
format.html { redirect_to folusers_url, notice: 'Foluser was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_foluser
#foluser = Foluser.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def foluser_params
params.require(:foluser).permit(:name, :email, :numberphone, :password)
end
end
foluser model
class Foluser < ApplicationRecord
belongs_to :admin, :optional => true
end
admin model
class Master < ApplicationRecord
has_many :foluser
end
Using your current code, setting the id_watch can be done here in the controller:
class FolusersController < ApplicationController
def create
#foluser = current_master.folusers.build(foluser_params)
#foluser.id_watch = current_master.id_watch # <-- !!!
respond_to do |format|
if #foluser.save
# ...
end
end
end
end
Despite our extended conversation above, I'm still unclear what you're trying to achieve with the "password generation".
(Should it be generated in the front-end, or the back-end? Should it be stored encrypted, or in plain text? If encrypted, do you need to be able to reverse this encryption? Is it a "permanent" password, or a "temporary" password? ...)
Therefore, the following code should be taken with a big pinch of salt - since I still don't really know what the desired/correct behaviour is.
In the FolusersController, you've defined the following method:
def foluser_params
params.require(:foluser).permit(:name, :email, :numberphone, :password)
end
However, if you want the password to be generated by the server then you shouldn't be allowing the admin to set the password through the controller. Therefore, remove this parameter:
def foluser_params
params.require(:foluser).permit(:name, :email, :numberphone)
end
And then somewhere - perhaps in the controller, or as a hook in the model - set this password to something random:
class FolusersController < ApplicationController
def create
#foluser = current_master.folusers.build(foluser_params)
#foluser.password = SecureRandom.hex(10 + rand(6))
# ...
end
end
# or
class Foluser < ApplicationRecord
after_initialize :default_password
def default_password
self.password ||= SecureRandom.hex(10 + rand(6))
end
end
I think you found the solution, use rails callbacks in your model to extract this kind of logic from the controller.
But I'd rather use after_initialize than before_save so that you won't set a default password before each save(so possibly even update action)
Then use things like SecureRandom (ActiveSupport concern) (already bundled by rails, no requires required)
after_initialize :defaultpassword
...
def default_password
self.password ||= SecureRandom.hex(10 + rand(6))
end
not the best way to do random I know but feel free to customize it.
secure_random output examples:
=>bf8d42b174d297f6460eef
=>efd28869171a1ec89c3438
=>3855c61fb6b90ed549d777
I am passing the ability to crop images, uploaded by Carrierwave. Here is RailsCast video on Youtube which I am following.
But after including RMagick in uploader, I received:
undefined method `marked_for_destruction?' for #<ImageUploader:0x007fe86634fcf0>
What a heck is this I thought. I haven't called this method anywhere. But if it is not defined, lets define it! And it worked! But later I checked more about this method and found that it is built in in Active Record Autosave Association module. And from docs, about this method:
Returns whether or not this record will be destroyed as part of the
parents save transaction.
Only useful if the :autosave option on the parent is enabled for this
associated model.
But I didn't passed autosave: true to any object!
So, my first question - was it done by default somehow?
2 - on RailsCast tutorial he didn't defined this method. Why I had to?
3 - I pass my code bellow. Any errors?
4 - if possible, could anyone explain how this process works, in general?
Many thanks!
product.rb:
has_one :image
validates :image, presence: true
mount_uploader :image, ImageUploader
products_controller.rb:
def create
#product = Product.new(product_params)
#product.category_id = params[:category_id]
#product.user_id = current_user.id
respond_to do |format|
if #product.save
if params[:product][:image].present?
format.html { render :crop }
else
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: #product }
end
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
image_uploader.rb:
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
def marked_for_destruction?
#marked_for_destruction
end
def mark_for_destruction
#marked_for_destruction = true
end
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :large do
resize_to_limit(600,600)
end
end
If you're using Rails 5:
Open up new_framework_defaults.rb and change:
Rails.application.config.active_record.belongs_to_required_by_default = true
to
Rails.application.config.active_record.belongs_to_required_by_default = false
config.active_record.belongs_to_required_by_default is a boolean
value and controls whether a record fails validation if belongs_to
association is not present.
Inside your the *_uploader.rb file just write the function:
def marked_for_destruction?
end
I'm trying to allow a user to input a date in a very permissive format (e.g. year only, year & month, or exact date). The date_time_precision gem seems perfect, but I'm a newbie and I can't figure out (beyond installing the gem) how to get my form to allow these various levels of precision (I've read the readme several times).
I'm using the simple_form gem with the following in the date portion of my _form:
<%= f.input :date,
:include_blank => true,
as: :string,
order: [ :year, :month, :day,],
hint: 'Order: Year, month, date' %>
The documentation has a heading called 'Usage', and then...
require 'date_time_precision'
But I can't figure out where to put that. Does it go somewhere in my controller?
Further info:
I did all the usual stuff (added gem to gemfile, bundle install, restart server, and refresh form page).
Updates:
My form seems pretty much broken now, I keep getting errors like "ActionController::ActionControllerError in ArtworksController#update
Cannot redirect to nil!"
My routes.rb file
Rails.application.routes.draw do
root "pages#home"
get "artworks" => "artworks#index"
# post "artworks" => "artworks#index"
resources :artworks #, path: ''
get "about" => "pages#about"
end
My controller:
class ArtworksController < ApplicationController
before_action :set_artwork, only: [:show, :edit, :update, :destroy]
# GET /artworks
# GET /artworks.json
def index
#artworks = Artwork.all
end
# GET /artworks/1
# GET /artworks/1.json
def show
#artwork = Artwork.friendly.find(params[:id])
if request.path != artwork_path(#artwork)
redirect_to #artwork, status: :moved_permanently
end
end
# GET /artworks/new
def new
#artwork = Artwork.new
end
# GET /artworks/1/edit
def edit
end
# POST /artworks
# POST /artworks.json
def create
#artwork = Artwork.new( artwork_params )
respond_to do |format|
if #artwork.save
format.html { redirect_to #artwork, notice: 'Artwork was successfully created.' }
format.json { render :show, status: :created, location: #artwork }
else
format.html { render :new }
format.json { render json: #artwork.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /artworks/1
# PATCH/PUT /artworks/1.json
def update
respond_to do |format|
if #artwork.update(artwork_params)
format.html { redirect_to #artworks, notice: 'Artwork was successfully updated.' }
format.json { render :show, status: :ok, location: #artwork }
else
format.html { render :edit }
format.json { render json: #artwork.errors, status: :unprocessable_entity }
end
end
end
# DELETE /artworks/1
# DELETE /artworks/1.json
def destroy
#artwork.destroy
respond_to do |format|
format.html { redirect_to artworks_url, notice: 'Artwork was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_artwork
#artwork = Artwork.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def artwork_params
params.require(:artwork).permit(:title, :image, :genre, :category, :medium, :slug, :availability, :date, :height, :width)
end
end
Sometimes it is desirable to manipulate dates or times for which incomplete information is known. For example, one might only know the year, or the year and the month. Unfortunately, Ruby's built-in Date, Time, and Date Time classes do not keep track of the precision of the data.
In above regard, the date_time_precision gem is used. Just to provide your helper methods to complete the date/time objects.
Your Case :
In your case in your view you need a date picker / time date picker(for a better use experience).
I would suggest go with bootstrap-datepicker-rails gem
Instructions are clearly stated in the github link :
1. Install Gem.
2. Mark the related js files required in your application.js file.
3. Add your datepicker / datetimepicker to a specific class (in document ready block)
4. Use the datetimepicker in your View.
The date_time_precision library extends Ruby's Date and Time classes to have a precision attribute which tracks if only the year is known, only the year and month, or the year, month, and day.
First, install the library as a gem with this:
gem install date_time_precision
Then, this code should work for you:
require 'date_time_precision'
def Date.parse_fuzzy(str)
if /\A\s*(\d{4})\s*\z/ =~ str
Date.new($1.to_i)
else
Date.parse(str)
end
end
That's just an extension of Date.parse that can also accept standalone years. Enjoy!
I have an issue with associating two models in my rails application: Users & Profiles. An individual user profile should be created after a new user signs up. After signing up the user, saving data into the actual profile model is not successful. I can not get it to work. Please find a detailed description below.
Here is my setup:
I use Rails 4.0.0.rc2 and ruby 2.0.0p195.
Both models are associated like this:
profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
end
user.rb
has_one :profile, dependent: :destroy
accepts_nested_attributes_for :profile
before_create :build_profile
As I use the devise gemI have created a registrationscontrollerto change the after_sign_up_path:
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
new_user_profile_path(:user_id => #user)
end
end
Whenever I sign up a new user the actual sign up works fine, the user is subsequently being directed to http://localhost:3000/users/42/profile/new for example. However, when I then enter the data into the profile form fields and click on submit I get the following error:
No route matches [POST] "/users/profile"
Although one could expect a routing error, you will notice a different error when looking at the actual domain:
http://localhost:3000/users//profile
In case you still want to have a look at my routes.rb please do (relevant excerpt):
devise_for :users, :controllers => { :registrations => "registrations" }
devise_scope :user do
get 'signup', :to => "devise/registrations#new", as: :signup
get 'login', :to => "devise/sessions#new", as: :login
get 'logout', :to => "devise/sessions#destroy", as: :logout
end
resources :users do
resource :profile
end
However, as noted above I don't really have a routing issue. It rather seems like I have an issue with the current user_id not being properly shown in the domain, which can be related to either my actual profile form or the new action on the profiles controller.
I start my profile form on new.html.erb like this:
<%= form_for #profile, url: user_profile_path(#user) do |f| %>
My profiles_controller.rblooks like this:
class ProfilesController < ApplicationController
before_action :set_profile, only: [:show, :edit, :update, :destroy]
# GET /profiles
# GET /profiles.json
def index
#profiles = Profile.all
end
# GET /profiles/1
# GET /profiles/1.json
def show
end
# GET /profiles/new
def new
#profile = Profile.new
end
# GET /profiles/1/edit
def edit
end
# POST /profiles
# POST /profiles.json
def create
#profile = Profile.new(profile_params)
respond_to do |format|
if #profile.save
format.html { redirect_to #profile, notice: 'Profile was successfully created.' }
format.json { render action: 'show', status: :created, location: #profile }
else
format.html { render action: 'new' }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /profiles/1
# PATCH/PUT /profiles/1.json
def update
respond_to do |format|
if #profile.update(profile_params)
format.html { redirect_to #profile, notice: 'Profile was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
# DELETE /profiles/1
# DELETE /profiles/1.json
def destroy
#profile.destroy
respond_to do |format|
format.html { redirect_to profiles_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_profile
##profile = Profile.find(params[:id])
#profile = current_user.profile
end
# Never trust parameters from the scary internet, only allow the white list through.
def profile_params
params.require(:profile).permit(:photo, :address, :zip, :city, :state, :country, :telephone, :experience, :levels, :ages, :travel, :teachinglocation, :onlineteaching, :quotation, :aboutme, :subjects, :specialties, :lessondetails, :equipment)
end
end
What do I do wrong? How can I properly ensure that a newly signed up user can properly save his profile data?
It would be so great, if you could help me out.
It appears the Profile controller is not configured with the correct url - as can be seen by the missing User ID information.
You can see all currently defined paths by running the command rake routes from the command line.
I am a beginner at RESTful design and Rails, so do not consider the following expert advice.
Try changing the location of your redirect_to in the Profile create method:
# POST /profiles
# POST /profiles.json
def create
...
format.html { redirect_to user_profile_path(#profile.user, #profile), notice: 'Profile was successfully created.' }
...
If this works, the path should also be updated in the update and delete methods. As well as the format.json sections.
For additional info about this topic see:
2.9 Creating Paths and URLs From Objects
http://guides.rubyonrails.org/routing.html
I'm running Rails 4 on Windows, and trying to automate a population script. My populatepins.rake file is:
namespace :db do
desc "Fill database with sample data"
task populatepins: :environment do
User.all.each do |user|
puts "[DEBUG] uploading images for user #{user.id} of #{User.last.id}"
2.times do |n|
image = File.open(Dir.glob(File.join(Rails.root, 'testpics', '*')).sample) # sample picks one random
puts "[DEBUG] searching for FILE: #{File.absolute_path(image)}"
description = %w(cool awesome crazy wow adorable incredible).sample # %W converts to an array
puts "[DEBUG] past description: #{description}"
user.pins.create!(image: image, description: description)
puts "[DEBUG] endofloop"
end
end
end
end
However, when running the script I get loops with this error:
C:\Sites\code\testrails>rake db:populatepins
[DEBUG] uploading images for user 45 of 47
[DEBUG] searching for FILE: C:/Sites/code/testrails/testpics/_MG_5557.jpg
[DEBUG] past description: adorable
C:/RailsInstaller/Ruby1.9.3/bin/rake: No such file or directory - lsof -p 13752
C:/RailsInstaller/Ruby1.9.3/bin/rake: No such file or directory - lsof -p 13752
C:/RailsInstaller/Ruby1.9.3/bin/rake: No such file or directory - lsof -p 13752
C:/RailsInstaller/Ruby1.9.3/bin/rake: No such file or directory - lsof -p 13752
[DEBUG] endofloop
I thought it might be the '\' vs '/' path problem as per https://www.ruby-forum.com/topic/194682, but couldn't really figure out a solution that worked...
Any help will be much appreciated, thanks!
EDIT: here is what the model looks like (JLX is me commenting...)
class Pin < ActiveRecord::Base
has_attached_file :image, styles: { large: "640x480>", medium: "320x240>", thumb: "200x200#"} # Paperclip association
validates :description, presence: true #, length: { minimum: 10 }
validates :user_id, presence: true
validates_attachment :image, presence: true,
content_type: { content_type: ['image/jpeg', 'image/jpg', 'image/png', 'image/gif']},
size: {less_than: 5.megabytes}
# JLX link to users
belongs_to :user # can only have one user associated
# We are modifying the default getter/setter method created automatically when generating the image_url var
def image_remote_url=(url_value)
self.image = URI.parse(url_value) unless url_value.blank?
super # inherits the default method behaviour
end
end
And this is what the controller looks like:
class PinsController < ApplicationController
# JLX Devise method
before_action :authenticate_user!, except: [:index, :show]
before_action :set_pin_global, only: [:show]
before_action :set_pin_user, only: [:edit, :update, :destroy]
# GET /pins
# GET /pins.json
def index
##pins = Pin.all
#pins = Pin.order("created_at desc")
end
# GET /pins/1
# GET /pins/1.json
def show
end
# GET /pins/new
def new
##pin = Pin.new
#pin = current_user.pins.new
end
# GET /pins/1/edit
def edit
end
# POST /pins
# POST /pins.json
def create
##pin = Pin.new(pin_params)
#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 action: 'show', status: :created, location: #pin }
else
format.html { render action: 'new' }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /pins/1
# PATCH/PUT /pins/1.json
def update
respond_to do |format|
if #pin.update(pin_params)
format.html { redirect_to #pin, notice: 'Pin was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
# DELETE /pins/1
# DELETE /pins/1.json
def destroy
#pin.destroy
respond_to do |format|
format.html { redirect_to pins_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_pin_global
#pin = Pin.find(params[:id])
end
def set_pin_user
#pin = current_user.pins.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, :image_remote_url) # JLX added :image
end
end