I am using Rails 4.1 and I created a User class. When the user is created the can import an avatar. However at best I have gotten an "image" to show up but it doesn't load the actual image from the database.
I then tried to use this post to fix it but now I am just getting "No Route Matches". Here is my exact error:
No route matches {:action=>"show_image", :controller=>"users_controller", :id=>"1"}
It claims it is coming from this line in my index.html.erb:
<%= image_tag url_for(:controller => "users_controller", :action => "show_image", :id => user.id) %>
Here is my controller:
def show_image
#user = User.find(params[:id])
send_data #user.avatar, :type => 'image/png', :disposition => 'inline'
end
And my users index.html.erb:
<html>
<head>
</head>
<body>
<h1>Users</h1>
<table>
<tr>
<th colspan="1"></th>
</tr>
<% #users.each do |user| %>
<tr>
<%= image_tag url_for(:controller => "users_controller", :action => "show_image", :id => user.id) %>
<td><%= user.username %></td>
</tr>
<% end %>
</table>
</body>
</html>
Any ideas or suggestions would be highly appreciated. Thanks ahead of time.
Edit: This is what my routes look like:
Rails.application.routes.draw do
get 'sessions/login'
get 'sessions/login_attempt'
get 'sessions/home'
get 'sessions/profile'
get 'sessions/setting'
get 'welcome/index'
get 'users/new'
post 'sessions/login_attempt'
post 'sessions/logout'
resources :users
root 'welcome#index'
end
Edit: I have also tried adding the following to the Routes file as suggested by #Question and #j0k in the thread I was following before:
resources :users do
get 'show_image', :on => :collection
end
and
get 'users/show_image' => 'users#show_image'
I also tried this
get 'users/show_image'
However I still got the same error.
Missing Image Icon that I get:
Two lines from my Users class where I add in avatar:
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
When looking up the images in the database this is what I found... I ran the following command:
sqlite> select avatar_file_name, avatar_content_type, avatar_file_size from users;
and got:
|image/png|660726
|image/gif|3614
|image/png|282
...so it is getting no file name.
When I looked up the file in the path I found that in this:
/public/system/users/avatars/000/000/001/original my image 'up.png' existed. It also existed in ../medium and ../thumb as well.
Edit: Update from #RichPeck advice.
So I was <%= image_tag #user.avatar.url %> ...instead this is what I was doing...
<% #users.each do |user| %>
<tr>
<%= image_tag user.avatar.url %>
</tr>
<% end %>
I am somewhat confused on how <%= image_tag #user.avatar.url %> would get a specific user's Avatar. Doesn't #user reference All Users? However, I tried #RichPeck suggestion anyway. I added both <%= image_tag #user.avatar.url %> and <%= debug #user.avatar %>. But both gave me the following error:
undefined method `avatar' for nil:NilClass
Edit: I just went through the Paperclip tutorial and compared it to what I have. I found a few differences but I don't think any of it would make a big difference. However, I will post it here so if anyone knows what is going wrong they can help.
Edit or New Views
Paperclip
<%= form_for #user, :url => users_path, :html => { :multipart => true } do |form| %>
<%= form.file_field :avatar %>
<% end %>
My code (The main thing I would be concerned about is the :url => but I think it should be fine)
<%= form_for(:user, :url => {:controller => 'users', :action => 'create'}, :html => { :multipart => true }) do |f| %>
<p> Username:</br> <%= f.text_field :username%> </p>
<p> Email:</br> <%= f.text_field :email%> </p>
<p> Password:</br> <%= f.password_field :password%></p>
<p> Password Confirmation:</br> <%= f.password_field :password_confirmation%> </p>
<%= f.file_field :avatar %>
<%= f.submit :Signup %>
<% end %>
Controller
Paperclip
def create
#user = User.create( user_params )
end
private
def user_params
params.require(:user).permit(:avatar)
end
My Code
def create
#user = User.new(user_params)
if #user.save
flash[:notice] = "You signed up successfully"
flash[:color]= "valid"
else
flash[:notice] = "Form is invalid"
flash[:color]= "invalid"
end
render "new"
end
private
def user_params
params.require(:user).permit(:username, :email, :password, :avatar)
end
Edit: After looking at it for a bit I realized I was trying to access the users page w/o my session. I was doing localhost:3000/users not localhost:3000/users?id=1. So my ID was never being passed.
I had to add the following to my Users Controller:
def index
#users = User.all
#user = User.find(params[:id]) # <--- Added this line
end
However, <%= image_tag #user.avatar.url %> still shows the default blank image. But I have been able to get <%= debug #user.avatar %> to work. This is the output for the debug command.
--- &70308396554900 !ruby/object:Paperclip::Attachment
name: :avatar
instance: !ruby/object:User
attributes:
id: 1
username: jones1
email: stupid1#stupid.com
encrypted_password: $2a$10$dvvLzRCQQVngFpt5TfPqJOtU8s02GUj6UOHlzibWi1CaQFY1BA8tS
salt: $2a$10$dvvLzRCQQVngFpt5TfPqJO
created_at: 2014-05-10 05:19:07.138281000 Z
updated_at: 2014-05-10 05:19:07.138281000 Z
avatar_file_name:
avatar_content_type: image/png
avatar_file_size: 397
avatar_updated_at: 2014-05-10 05:19:06.715067000 Z
options: &70308396554880
:convert_options: {}
:default_style: :original
:default_url: /images/:style/missing.png
:escape_url: true
:restricted_characters: !ruby/regexp /[&$+,\/:;=?#<>\[\]\{\}\|\\\^~%# ]/
:filename_cleaner:
:hash_data: ':class/:attachment/:id/:style/:updated_at'
:hash_digest: SHA1
:interpolator: &70308352640280 !ruby/module 'Paperclip::Interpolations'
:only_process: []
:path: ':rails_root/public:url'
:preserve_files: false
:processors:
- :thumbnail
:source_file_options: &70308351975980 {}
:storage: :filesystem
:styles:
:medium: 300x300>
:thumb: 100x100>
:url: /system/:class/:attachment/:id_partition/:style/:filename
:url_generator: !ruby/class 'Paperclip::UrlGenerator'
:use_default_time_zone: true
:use_timestamp: true
:whiny: true
:check_validity_before_processing: true
post_processing: true
queued_for_delete: []
queued_for_write: {}
errors: {}
dirty: false
interpolator: *70308352640280
url_generator: !ruby/object:Paperclip::UrlGenerator
attachment: *70308396554900
attachment_options: *70308396554880
source_file_options: *70308351975980
whiny: true
Edit: Last edit for the night before I have to go to sleep. I also did <%= debug #user.avatar.url %> and it returned the following: --- /images/original/missing.png?1399954308
Since you're using paperclip, and to help maintain clarity for anyone looking at this in future:
Paperclip
When you use Paperclip, it creates an object & appends to your
original ActiveRecord object. When you define has_attached_file :____, the name of that element is what the Paperclip object is
called, meaning you'll be able to call #user.____ to access it
The problem you have is you're using another process to load your image. This is totally unnecessary as, as pointed out in the comments, Paperclip automatically assigns the .url method to the appended Paperclip object
You should be able to call <%= image_tag #user.avatar.url %> to output the relvant image. I know you know this, but I want to help anyone who may look at this thread in future
Error
In terms of your error, having looked at your comments & updates, it seems like it's either a problem with how you're calling the image, or perhaps how it's stored in the db
Can you do this for us:
<%= debug #user.avatar #-> this will show the entire avatar object %>
I believe your db will not have the correct columns, hence Paperclip pulling the wrong filename or something. There will be a really trivial error somewhere
In general the setup appears to be fairly complicated - considering you want to display a user image. For simply things like user image I am using paperclip for my projects: https://github.com/thoughtbot/paperclip .. you may want to take a look at it. It automates image upload, resize, etc. I used it in several projects and never hit any issues.
If that's not what you need, perhaps you let me know what exactly you are trying to do.
Related
I've got a Rails application that is using nested forms. Details follow and I tried this solution (Rails 3 Nested Models unknown attribute Error), but for some reason, the field is repeating multiple times instead of listing and saving the options correctly. Thanks in advance for your help!
Model information for Newsavedmaps
has_many :waypoints, :dependent => :destroy
accepts_nested_attributes_for :waypoints
Newsavedmap_controller
def new
#newsavedmap = Newsavedmap.new
waypoint = #newsavedmap.waypoints.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #newsavedmap }
end
end
def edit
#newsavedmap = Newsavedmap.find(params[:id])
if #newsavedmap.itinerary.user_id == current_user.id
respond_to do |format|
format.html # edit.html.erb
format.xml { render :xml => #activity }
end
else
redirect_to '/'
end
end
Maptry View
<% form_for #newsavedmap, :html=>{:id=>'createaMap'} do |f| %>
<%= f.error_messages %>
<% f.fields_for :waypoint do |w| %>
<%= w.select :waypointaddress, options_for_select(Waypoint.find(:all, :conditions => {:newsavedmap_id => params[:newsavedmap_id]}).collect {|wp| [wp.waypointaddress, wp.waypointaddress] }), {:include_blank => true}, {:multiple => true, :class => "mobile-waypoints-remove", :id =>"waypoints"} %>
<% end %>
<% end %>
When I use the above code, my form works correctly, but submitting it gives me this error:
UnknownAttributeError (unknown attribute: waypoint)
When I change ":waypoint do |w|" to ":waypoints do |w|" in the view, the select field disappears when the user is creating a new record, and in the edit view, the select field appears several times (however many waypoints the user saved in the record.)
How can I get this form field to work properly?
EDIT 1
Here is my latest attempt. For new records, the select field does not appear. However, in the edit view, the select field appears multiple times. This is a Rails 2 application, FYI. Taking a cue from the comments, I used a collection_select approach (not collection_for_select because I couldn't find documentation for that.) Again, I appreciate your help!
<% f.fields_for :waypoints do |w| %>
<%= w.collection_select( :waypointaddress, #newsavedmap.waypoints, :waypointaddress, :waypointaddress, {:include_blank => true}, {:id =>"waypoints"} ) %>
<% end %>
Your form has the following problems.
Use f.fields_for :waypoints since the argument needs to match the name of the association.
Use collection_select rather than select, since you have an ActiveRecord model behind that field.
So, taking that into account, you could try this for your form:
<% form_for #newsavedmap, :html => { :id => 'createaMap' } do |f| %>
<%= f.error_messages %>
<% f.fields_for :waypoints do |w| %>
<%= w.collection_for_select :waypoint, :waypointaddress, #newsavedmap.waypoints, :waypointaddress, :waypointaddress, { :include_blank => true }, { :multiple => true, :class => "mobile-waypoints-remove", :id =>"waypoints" } %>
<% end %>
<% end %>
The API for collection_select is a bit tricky to get right. I usually need a few attempts as well. This previous SO question may help clear things up: Can someone explain collection_select to me in clear, simple terms?
Believe you can help me.
I'm trying to add new functionality to legacy code (Typo). But it seems that there is some problem about routing.
In the project routes are generated the following way:
%w{advanced cache categories comments content profiles feedback general pages
resources sidebar textfilters themes trackbacks users settings tags redirects seo post_types }.each do |i|
match "/admin/#{i}", :to => "admin/#{i}#index", :format => false
match "/admin/#{i}(/:action(/:id))", :to => "admin/#{i}", :action => nil, :id => nil, :format => false
end
My functionality is about merging articles. For that I've added new action in the /admin/content controller:
def merge
#some code here
end
A piece of a view partial (_form.html.erb) added by me:
<% if current_user.admin? and !#article.id.nil?%>
<div class=''>
<h4><%= _("Merge Articles") %></h4>
<%= label_tag :merge_with, 'Article ID' %><%= text_field_tag :merge_with, nil, :size => 20 %>
<%= button_to 'Merge', admin_content_merge_path(:id => #article.id) %>
</div>
<%end%>
This partial is rendered by another partial (_edit.html.erb)
<%= form_tag(form_action, :id => "#{form_type}_form", :enctype => "multipart/form-data", :class => className) do %>
<%= render :partial => "form" %>
<% end %>
And finally _edit.html.erb is rendered by view new.html.erb
<%= render "admin/shared/edit", { :form_type => "article", :form_action => { :action => "new", :id => #article.id , :class => ('autosave')} } %>
The problem is how to write a correct route for the controller action above which will allow me to render an edit page containing newly merged article. I wrote:
match "/admin/content/merge/:id" => "admin/content#merge",:as => 'admin/content/merge'
rake routes output:
admin_content_merge /admin/content/merge/:id(.:format) {:controller=>"admin/content", :action=>"merge"}
But the new or edit action is being invoked as I can see.
Apparently, my route is wrong, isn't it?
Could you please help me with this.
Thanks in advance!
Update
Up-to-date new.html.erb:
<% #page_heading = _('New article') %>
<%= render "admin/shared/edit", { :form_type => "article", :form_action => { :action => "new", :id => #article.id , :class => ('autosave')} } %>
<% if current_user.admin? and !#article.id.nil?%>
<%= form_tag "/admin/content/merge/#{#article.id}" do %>
<h4><%= _("Merge Articles") %></h4>
<%= label_tag :merge_with, 'Article ID' %>:
<%= text_field_tag :merge_with %><br />
<%= submit_tag "Merge" %>
<% end %>
<% end %>
Read the hint from the course:
HINT:Nesting is invalid in HTML.
That means that you can't nest form tags, don't put the form tag in another form tag, your nested form wont be able to do a correct action.
Since you have to put your code at the end of the page, try and see how to do it with having your merging form tag below the main edit article form tag. So basically you can find where the big form tag ends and put it below it.
Try to see if you can figure it out, and if not, don't hesitate to ask :)
Btw. I think everybody had some problem with this
Tis is my view:
<%= form_for item, :url => comment_item_path(item), :html => {:remote => true, 'portal-transform' => true, :multipart => true} do |f| -%>
<%= f.fields_for :updates, Update.new, :index => nil do |m| -%>
<%= m.text_area :comment %><br />
<%= m.file_field :attachment %>
<% end -%>
<%= f.submit "Comment" %>
<% end -%>
And controller action:
respond_to do |format|
format.js do
render :json => {}
end
end
When I submit the form with only comment (text_area) field entered and keep attachment (file_field) field blank, it render exactly what expected.
But when I submit the form with attachment, it resulted in:
Completed 406 Not Acceptable in 56ms
What went wrong for me? Please guide.
Thanks.
Browsers do not allow file uploads via AJAX for security reasons. If you leave the form's file_field blank however, the form submits normally with no error, which explains the behaviour you are seeing.
To upload files via AJAX in Rails 3, you can use the Remotipart gem.
http://os.alfajango.com/remotipart/
Here is an example usage:
http://thechangelog.com/post/7576700785/remotipart-rails-3-ajax-file-uploads-made-easy
I have a partial in my rails app that loads the vote form (It's just a select with numbers ranging from 1-5). I'm now making another partial that loads up if the user has already voted it's suppose to be an EDIt partial where you get selected the value that you voted and if you wanted to you could change it. But for some reason is not working, here's the code for it.
#Finds the vote by passing the user and the article
<%= #vote = Vote.find_vote_by(current_user,#article) %>
#Renders the partial with the vote variable loaded up with the vote that was found
<%= render :partial => "votes/edit_vote", :locals => {:vote => #vote} %>
And this is the partial
<% form_for(vote, :url => {:controller => 'votes', :action => 'edit'}) do |f| %>
<%= error_messages_for :vote %>
<p><%= f.hidden_field :article_id %></p>
<p>
<%= f.label :value, "Value for the vote: "%>
<%= f.select :value, {"1" => "1","2" => "2","3" => "3","4" => "4", "5" => "5"}, :selected => vote.value %>
</p>
<p>
<%= f.submit "Cloud-it!" %>
</p>
<% end %>
But for some reason the vote variable is not containing anything not the article_id, nor the value method, any ideas?
EDIT1: Per request here's what's debug #vote is outputting (It it indeed a sane value)
attributes:
created_at: 2010-09-02 14:39:04
updated_at: 2010-09-02 14:39:04
id: 1
value: 4
article_id: 1
user_id: 1
attributes_cache: {}
EDIT2
I tried clearing the partial code, in order to output this:
<%= debug #vote%>
<%= #vote.value %>
If i debug #vote it comes out perfect, will all the attributes and such. But whenever i add the second line it, It's not working it tells me that there's no .value, i tried .id, .article and nothing is as if it didn't exist. Any ideas?
EDIT3
Here's the vote by
named_scope :find_vote_by, lambda {|user,article| {:conditions => {:user_id => user, :article_id => article}}}
The reason behind it, it's that named scopes actually return named scopes, and you can't access the attributes just like it were a Vote class. I fixed this by changing the way to retrieve the vote and just forgetting about using that named scope. I accomplished it by using:
<% #vote = current_user.votes.find_by_article_id(#article)%>
which is a Rails method and actually returns a vote class. Then i just passed it to the partial and the magic worked!
Thank you so much to thenduks, without his help i couldn't had done it.
So first thing to fix is this line:
<%= #vote = Vote.find_vote_by(current_user,#article) %>
Should be:
<% #vote = Vote.find_vote_by(current_user,#article) %>
The former is for outputting in ERB and the latter is for executing arbitrary ruby code.
Next, put a line below that like so:
<%= debug #vote %>
And make sure it's a sane value. If not, paste the definition of your Vote class method find_vote_by.
EDIT: In that case it's probably just because using :locals => {...} makes instance variables, so you want #vote in your partial with the form.
I've been looking at the new options available in HTML5 forms, such as declaring input types as "email", "url", and "number", as described here.
How can I use these in conjunction with the rails form builders? I have tried
<% form_for #user do |f| %>
<%= f.email :email, {:placeholder => 'user#domain.com'} %>
<% end %>
But that does not work. I've also tried
<% form_for #user do |f| %>
<%= f.text_field :email, {:placeholder => 'user#domain.com', :type => :email} %>
<% end %>
But the type is still "text" and not overridden. Is it possible, or is this something that will need to be addressed in Rails itself?
Looks like there is currently an open ticket and patch for adding the HTML5 form input types. If you can't wait until the patch is accepted, you could apply the patch locally by freezing the actionpack gems and applying the patch or making an initializer that add the extra methods.
Of course the other option is adding the fields manually without a form helper:
<% form_for #user do |f| %>
<%= tag(:input, {:type => :email, :value => f.object.email} %>
<% end %>
There is now an email_field tag.