I switched from a Sony computer to an Asus, downloaded the same programs as I had on the Sony and cloned my Rails 4.0.10 project from Bitbucket. Everything else behaves the same, but Paperclip has inexplicably stopped working, though the two development environments should be exactly the same. I used Paperclip to add an avatar to my User model, but now User.create fails when I attach an avatar. I tried uninstalling and reinstalling it, but that made no difference. Does anyone with Paperclip experience know what might have happened?
Gemfile:
gem "paperclip", :git => "git://github.com/thoughtbot/paperclip.git"
# ...
models/user.rb
class User < ActiveRecord::Base
has_attached_file :avatar, :styles => { :large => "500x500", :medium => "300x300>", :thumb => "50x50!" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
# ...
controllers/users.rb
class UsersController < ApplicationController
def create
# ...
if #user.save
render :action => "crop"
else
flash[:notice] = "Failed"
redirect_to new_user_path
end
end
private
def user_params
params.require(:user).permit(:name, :avatar)
end
views/users/new.html.erb
<%= form_for #user, :url => users_path, :html => { :multipart => true } do |f| %>
<%= f.text_field :name, :placeholder => "Name" %>
<br>
<%= f.label :display_picture %>
<%= f.file_field :avatar %>
<br>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
views/users/crop.html.erb
<% content_for(:head) do %>
<%= stylesheet_link_tag "jquery.Jcrop" %>
<%= javascript_include_tag "jquery.Jcrop.min" %>
<script type="text/javascript" charset="utf-8">
ready = $(function() {
$("#cropbox").Jcrop();
});
</script>
<% end %>
$(document).ready(ready);
$(document).on('page:load', ready);
<%= image_tag #user.avatar.url(:large), :id => "cropbox" %>
Make sure imagemagick is installed on your machine. This isn't something 'bundle install' will cover.
Follow the instructions here
http://www.imagemagick.org/script/install-source.php
Or use homebrew or other package managers
Related
In this code I was trying to remove fileds for nested_attributes using ajax :remote => ture to avoid reloading
the whole page in browser. Although fileds in fields_for was removed from DOM and association was removed from database, the fields of the nested attributes
still exist in page source and raise ActiveRecord::RecordNotFound error when trying to send params to update action of parent model
consider the following code:
_artist_form.html.erb
<%= form_for #artist do |f| %>
<%= f.label :name %>
<%= f.text_field :name %><br/>
<%= f.label :style %>
<%= f.text_field :style %><br/>
<%= f.fields_for :songs do |song_builder|%>
<div id = 'song_<%= song_builder.object.id %>_div'>
<%= song_builder.label :title %>
<%= song_builder.text_field :title %><br/>
<%= song_builder.label :lyrics %>
<%= song_builder.text_area :lyrics %><br/>
<%= link_to 'Remove song', delete_song_path(:a_id => #artist.id, :s_id => song_builder.object.id),
:method => :delete , :remote => true %>
</div>
<% end %>
<%= f.submit 'Save' %>
<% end %>
routes.rb
Rails.application.routes.draw do
...
delete '/artists/remove_song', :to => 'artists#delete_song', :as => :delete_song
end
application_controller.rb
class ArtistsController < ApplicationController
def edit
...
end
def update
#artist = Artist.find(params[:id])
if #artist.update(artist_params) #=> error Couldn't find Song with ID=2 for Artist with ID=2
redirect_to artist_path(#artist)
else
flash[:errors] = #artist.errors.full_messages
render :edit
end
end
...
def delete_song
#song_id = params[s_id]
aritst = Artist.find(:params[a_id])
song = artist.songs.find(#song_id)
song.delete
respond_to do |format|
format.js {render 'delete_song.js.erb'}
end
end
end
delete_song.js.erb
$('#song_<%= #song_id %>_div').remove() ;
Error
Couldn't find Song with ID=2 for Artist with ID=2
how to prevent sending params of removed fields by $(...).remove() to update action?
I tried to find a solution for this error. So according to charlietfl comment, I tried to store delete status somewhere locally, then rails can delete association later. So I modified the code as following:
deleting all remote script code including delete_song.js.erb file and delete_song action and delete route. then I allowed marking nested attribute for delete in Artist model file:
accepts_nested_attributes_for :songs, :allow_destroy => true
then adding delete button in _artist_form.html.erb file as following:
<%= button_tag 'x' , :class => 'close_sign', :type => 'button', :onclick => "$('#song_#{song_builder.object.id}_destroy').val('true'); $('#song_#{song_builder.object.id}_div').hide()" %><br/>
and a hidden flied to fields_for as below:
<%= song_builder.hidden_field :_destroy, :id => "song_#{song_builder.object.id}_destroy" %>
and allowing :songs_nested_attributes => [:title, :lyrics, :_destroy] in song_params
once user remove the song field, it will be hidden and marked for destroy later
Im trying to update my create item action to work with Ajax but Im getting an error of undefined methoditem_path` which i wasn't getting before when it was responding in regular html format. The item is created and saved but ajax doesn't seem to work properly though.
Here is my _from partial :
<%= form_for [#user, item], remote: true do |f|%>
<div class="form-group">
<%= f.label :name, class: 'sr-only' %>
<%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
</div>
<%= f.submit "Submit Item", class: 'btn btn-primary pull-right' %>
<% end %>
item#create:
def create
#item = Item.new(item_params)
#item.user = current_user
if #item.save
flash[:notice] = 'Item saved successfully.'
else
flash[:alert] = 'Item not saved. Title is too short or missing. Please try again.'
end
respond_to do |format|
format.html
format.js
end
end
create.js.erb:
$('.js-items').prepend("<%= escape_javascript(render(#item)) %>");
$('.new-item').html("<%= escape_javascript(render partial: 'items/form', locals: {user: #user , item: #item }) %>");
User#show view
<div class='new_item'>
<%= render :partial => 'items/form', :locals =>{:item => Item.new , :user => #user} %>
</div>
<div class='js-items'>
<%= render #user.items %>
</div>
routes:
user_items GET /users/:user_id/items(.:format) items#index
POST /users/:user_id/items(.:format) items#create
new_user_item GET /users/:user_id/items/new(.:format) items#new
edit_user_item GET /users/:user_id/items/:id/edit(.:format) items#edit
user_item GET /users/:user_id/items/:id(.:format) items#show
PATCH /users/:user_id/items/:id(.:format) items#update
PUT /users/:user_id/items/:id(.:format) items#update
DELETE /users/:user_id/items/:id(.:format) items#destroy
The error im getting in rails s :
ActionView::Template::Error (undefined method `item_path' for #<#<Class:0x007fa4f0d30cd8>:0x007fa4f31b26b0>):
1: <%= form_for [#user, item], remote: true do |f|%>
2: <div class="form-group">
3: <%= f.label :name, class: 'sr-only' %>
4: <%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
app/views/items/_form.html.erb:1:in `_app_views_items__form_html_erb__331698480542899910_70173200751480'
app/views/items/create.js.erb:2:in `_app_views_items_create_js_erb___3618987352886002527_70173200313760'
app/controllers/items_controller.rb:17:in `create'
Do something like that.
<%= form_for [#user, item], user_items, remote: true do |f|%>
If it doesn't work then run
rake routes
in terminal see what's your path.
I'm trying to use Dropzone.js with Rails 4, and although I can get the actual Dropzone 'zone' to appear, when I try to upload images, the following
Template is missing Missing template projects/show, application/show with {:locale=>[:en], :formats=>[:json], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}
However, I'm quite sure that I have the template, as images that are being uploaded without Dropzone are uploading and displaying fine
My code is as follows:
ProjectImagesController:
class ProjectImagesController < ApplicationController
def create
#project = Project.find(params[:project_id])
#project_image = #project.project_images.create(project_image_params)
redirect_to project_path(#project)
end
private
def project_image_params
params.require(:project_image).permit(:caption, :image)
end
end
projects/show.html.erb
<% if #project.project_images.any? %>
<% #project.project_images.each do |project_image|%>
<ul>
<li><%= image_tag project_image.image.url(:thumb) %></li>
<li><%= project_image.caption %></li>
</ul>
<% end %>
<% end %>
<%= simple_form_for [#project, #project_image], :html => {:multipart => true, class: :dropzone} do |f| %>
<div>
<%= f.input :caption, label: 'Enter your project image caption' %>
<%= f.file_field :image %>
<%= f.submit 'Create project image'%>
</div>
Thank you for your help in advance.
dropzone sends request in JSON format, but you try to render HTML, so you have to change your controller:
from
def create
#project = Project.find(params[:project_id])
#project_image = #project.project_images.create(project_image_params)
redirect_to project_path(#project)
end
to
def create
#project = Project.find(params[:project_id])
#project_image = #project.project_images.create(project_image_params)
render nothing: true
end
or something else in JSON format
hope I'll help somebody...
I am implementing 'acts_as_commentable_with_threading' and the js script is not working with the delete or create actions. I have to reload the page for my comments to be added and removed from the page.
I have placed my 'comments.js.coffee' file in the 'app/assets/javascript' directory. It looks like the following:
#comments.js.coffee
jQuery ->
# Create a comment
$(".comment-form")
.on "ajax:beforeSend", (evt, xhr, settings) ->
$(this).find('textarea')
.addClass('uneditable-input')
.attr('disabled', 'disabled');
.on "ajax:success", (evt, data, status, xhr) ->
$(this).find('textarea')
.removeClass('uneditable-input')
.removeAttr('disabled', 'disabled')
.val('');
$(xhr.responseText).hide().insertAfter($(this)).show('slow')
# Delete a comment
$(document)
.on "ajax:beforeSend", ".comment", ->
$(this).fadeTo('fast', 0.5)
.on "ajax:success", ".comment", ->
$(this).hide('fast')
.on "ajax:error", ".comment", ->
$(this).fadeTo('fast', 1)
#In Comments controller file I wrote:
def create
#comment_hash = params[:comment]
#obj = #comment_hash[:commentable_type].constantize.find(#comment_hash[:commentable_id])
# Not implemented: check to see whether the user has permission to create a comment on this object
#comment = Comment.build_from(#obj, current_user, #comment_hash[:body])
if #comment.save
render :partial => "comments/comment", :locals => { :comment => #comment }, :layout => false, :status => :created
else
render :js => "alert('error saving comment');"
end
end
def destroy
#comment = Comment.find(params[:id])
if #comment.destroy
render :json => #comment, :status => :ok
else
render :js => "alert('error deleting comment');"
end
end
end
# In Catalogs controller the code is:
def find_user
#member = Member.find(params[:id])
end
def show_user
find_user
#comments = #member.comment_threads.order('created_at desc')
#new_comment = Comment.build_from(#member, #member.id, "","")
respond_to do |format|
format.html # show.html.erb
format.json { render json: #member }
end
end
#In Comments model, the code include:
acts_as_nested_set :scope => [:commentable_id, :commentable_type]
attr_accessible :commentable, :body,:member_id,:sender
validates :body, :presence => true,:length=>{:maximum=>1000}
validates :member, :presence => true,:length=>{:maximum=>200}
validates :sender,:presence=> true,:length=>{:maximum=>200}
belongs_to :commentable, :polymorphic => true
# NOTE: Comments belong to a user
belongs_to :member
def self.build_from(obj, member_id, comment,sender)
new \
:commentable => obj,
:member_id => member_id,
:body => comment,
:sender => sender
end
...................
# In Member model, I add the following lines:
acts_as_commentable
has_many :comments, :dependent=>:destroy
# In the view file 'show_user', I wrote:
<div class='comments'>
<%= render :partial => 'comments/form', :locals => { :comment => #new_comment }%>
<%= render :partial => 'comments/comment', :collection => #comments, :as => :comment %>
</div>
#Partial 'comments/comment' contains:
<div class='comment'>
<hr>
<b><%= comment.sender %> </b>
<small><%= comment.updated_at%></small> <%= link_to "×",comment_path(comment), :method => :delete, :remote => true, :confirm => "Are you sure you want to remove this comment from # {comment.sender}?", :disable_with => "×", :class => 'close'%>
<p><%= comment.body.html_safe%></p>
</div>
# In _form.html.erb file:
<div class='comment-form'>
<%= simple_form_for comment, :remote => true do |f|%>
<small>Leave your comment </small><br/>
<%= f.input :sender,:as => :hidden,:input_html => { :rows => "2", :value =>"# {current_user.login}"}, :label => false %>
<%= f.input :body, :input_html => { :rows => "2", :class =>"tinymce"}, :label => false %>
<%= f.input :commentable_id, :as => :hidden, :value => comment.commentable_id %>
<%= f.input :commentable_type, :as => :hidden, :value => comment.commentable_type %>
<%= f.button :submit, :class => "btn btn-primary", :disable_with => "Submitting…" %>
<%end%>
</div>
In config/routes file:
resources :comments, :only => [:create, :destroy]
#Here is the output I get if I click on to 'create comments' button:
I hope someone will help me. Thank you.
I **deleted** the jquery.min.js file from my app/assets/javascripts directory
and in my gem file I added the line : gem 'jquery-rails'
and used 'bundle install' to use the gem in my app.
The application.js file has three lines:
//= require jquery
//= require jquery_ujs
//= require_tree .
And in my layout.html.erb file I have the line:
<%= javascript_include_tag 'application' %>
I know it is pretty obvious. Sometimes you need to get things wrong
to understand the obvious better. Now I can add and remove
messages using AJAX and js files.
Thanks for your time.
I am working on rails 3.2 and I am using gems simple_form, cocoon, and rails3-jquery-autocomplete.
I have following models Machine, Part, PartUsage, MachineCosting and PartCosting
Machine and Part models with many-to-many association.
class Machine < ActiveRecord::Base
attr_accessible :name
has_many :part_usages
has_many :parts, :through => :part_usage
end
class Part < ActiveRecord::Base
attr_accessible :name
end
class PartUsage < ActiveRecord::Base
attr_accessible :machine_id,
:part_id
belongs_to :part
belongs_to :machine
end
MachineCosting and PartCosting models with one-to-many association.
class MachineCosting < ActiveRecord::Base
attr_accessible :machine_id,
:total_cost,
:machine_name,
:part_costings_attributes
attr_accessor :machine_name
has_many :part_costings, :dependent => :destroy
accepts_nested_attributes_for :part_costings, :allow_destroy => true
def machine_name
self.machine.try(:name)
end
end
class PartCosting < ActiveRecord::Base
attr_accessible :part_id,
:part_name,
:cost
attr_accessor :part_name
belongs_to :machine_costing
belongs_to :part
def part_name
self.part.try(:name)
end
end
Form for MachineCosting
views/machine_costings/_form.html.erb
<%= simple_form_for(#machine_costing, :html => {:multipart => true}) do |f| %>
<%= f.input :machine_id, :url => autocomplete_machine_id_machines_path,
:as => :autocomplete %>
<!-- HERE, WHENEVER I SELECT A MACHINE, I WANT TO ADD NESTED-FORMS FOR
PARTCOSTINGS CORRESPONDING TO ALL THE PARTS OF THE MACHINE I JUST SELECTED.-->
<%= f.simple_fields_for :part_costings do |part_costing|%>
<%= render 'part_costings/part_costing_fields', :f => part_costing %>
<% end %>
<% end %>
Please suggest how can I populate and dynamically add fixed no of fields for PartCostings using javascript after machine_id is selected in the field.
I would be happy to provide any more information.
Thanks again!!
First, summary of my approach.
In MachineCosting form, use 'rails3-jquery-autopopulate' gem to search for Machines by their name.
Hack MachineController to also send 'Parts info' together with matching machines in json form.
When user selects a machine, use javascript to add nested_forms for PartCostings and partially populate them using data recieved in json form.
Now here is how I have done it (code part).
views/machine_costings/_form.html.erb
<%= simple_form_for(#machine_costing, :html => {:multipart => true}) do |f| %>
<%= f.error_notification %>
<%= f.input :machine_name, :url => autocomplete_machine_name_machines_path,
:as => :autocomplete, :input_html => { :id_element => "#machine_costing_machine_id"} %>
<%= f.association :machine, :as => :hidden %>
<div id='part_costings'>
<%= f.simple_fields_for(:part_costings) do |part_costing|%>
<%= render 'part_costings/part_costing_fields', :f => part_costing %>
<% end %>
<div class="links hidden">
<%= link_to_add_association 'Add part costings', f, :part_costings,
:partial => 'part_costings/part_costing_fields' %>
</div>
</div>
<%= f.button :submit%>
<% end %>
views/part_costings/_part_costing_fields.html.erb
<div class= 'nested-fields'>
<!-- DO NOT CHANGE THE ORDER OF ATTRIBUTES ELSE machine_costing.js WILL FAIL -->
<%= f.input :part_id, :as=> :hidden %>
<%= f.text_field :part_name, :disabled => 'disabled' %>
<%= f.input :cost %>
<%= link_to_remove_association '<i class="icon-remove"></i>'.html_safe, f ,:class =>"part_costing_remove" %>
</div>
controllers/machines_controller.rb
class MachinesController < ApplicationController
# OVER RIDING THIS BY OWN METHOD
# autocomplete :machine, :name, :full=> true, :extra_data => [:machine_id]
def autocomplete_machine_name
respond_to do |format|
format.json {
#machines = Machine.where("name ilike ?", "%#{params[:term]}%")
render json: json_for_autocomplete_machines(#machines)
}
end
end
def json_for_autocomplete_machines(machines)
machines.collect do |machine|
parts = Hash.new
unless machine.part_usages.empty?
machine.part_usages.each do |part_usage|
parts[part_usage.part.id] = part_usage.part.name
end
end
hash = {"id" => machine.id.to_s, "value" => machine.name,
"parts" => parts}
hash
end
end
#
#
#
end
And here is the javascript part.
assest/javascripts/machine_costings.js
$(function() {
// Part Costings
var part_id;
var part_name;
$('#machine_costing_machine_name').bind('railsAutocomplete.select', function(event, data){
console.debug("Machine selected...");
parts = data.item.parts;
console.debug("Removing existing part_costings...");
$('.part_costing_remove').click();
console.debug("Adding part_costings...");
for(var id in parts) {
part_id = id;
part_name = parts[id];
$('.add_fields').click();
}
console.debug("Done adding all part_costings...");
});
$('#part_costings').bind('cocoon:after-insert', function(e, part_costing) {
part_costing[0].getElementsByTagName('input')[0].value = part_id;
part_costing[0].getElementsByTagName('input')[1].value = part_name;
console.debug("Added part_costing...");
});
});
routes.rb
resources :machines do
get :autocomplete_machine_name, :on => :collection
end
The critical points in javascript solution are...
Method "bind('railsAutocomplete.select', function(event, data)" from rail3-jquery-autocomplete gem.
Method "bind('cocoon:after-insert', function(e, part_costing)" from cocoon gem.
That's all.
Please let me know if you have some suggestions. Thanks :)