I am having trouble implementing the DELETE action on any object that I have for my application.
To show you the general code for my delete action in the Group Controller:
def destroy
#group = Group.find(params[:id])
respond_to do |format|
if #group.delete
format.html { redirect_to group_path }
format.json { head :no_content }
else
format.html { redirect_to group_path }
format.json { head :no_content }
end
end
end
And the code for my View layout:
<h1>My Groups</h1>
<table>
<tr>
<th>Name</th>
<th>Users</th>
<th></th>
<th></th>
</tr>
<% #groups.each do |group| %>
<tr>
<td><%= group.name %></td>
<td>
<% group.memberships.each do |membership| %>
<%= User.find(membership.user_id).name %>
<br/>
<% end %>
</td>
<td><%= link_to 'Show', group %></td>
<td><%= link_to 'Destroy', group, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Group', new_group_path %>
I am unable to delete the group object even though the rails server log gives me back a 200 OK response. The returned page is a blank screen:
Started DELETE "/groups/2" for 127.0.0.1 at 2013-03-19 01:22:01 +0800
Processing by GroupsController#destroy as HTML
Parameters: {"authenticity_token"=>"aH+z0DlL7NeoVlxda8Td76WdnrH7/G8UyWDqbJcTu9w=", "id"=>"2"}
Completed 200 OK in 0ms (ActiveRecord: 0.0ms)
ActiveRecord wasn't used and there were no changes to the database. There were no such problems in the past, but I only realized that I could not delete any kind of object recently.
I have been trying to find solutions to similar problems found on the net, but unfortunately it seems like no one has had this problem yet.
Update 1:
The following is my application layout:
<!DOCTYPE html>
<html>
<head>
<%= csrf_meta_tag %>
<title>Home</title>
<%= javascript_include_tag :application %>
<%= stylesheet_link_tag :application, :media => "all" %>
<%= javascript_include_tag "/javascripts/main.js" %>
<%= stylesheet_link_tag "/css/main.css" %>
</head>
<body>
<%= yield %>
</body>
</html>
But when I use the console to delete the object. It works:
1.9.3-p194 :003 > Group.find(23).delete
Group Load (0.5ms) SELECT "groups".* FROM "groups" WHERE "groups"."id" = $1 LIMIT 1 [["id", 23]]
SQL (3.0ms) DELETE FROM "groups" WHERE "groups"."id" = 23
=> #<Group id: 23, name: "groupie", created_at: "2013-03-18 15:29:42", updated_at: "2013-03-18 15:29:42", user_id: nil>
I just found the solution to the question. I actually wrote a code for an around_filter that messed up the destroy session for every controller:
around_filter :clear_registration_id_on_destroy_session, only: :destroy
def clear_registration_id_on_destroy_session
is_filter_active = (controller_path == 'devise/sessions' && params[:action] == 'destroy')
if is_filter_active && user_signed_in?
if current_user.update_attribute(:device_platform, nil)
logger.info "Updated device platform attributes to nil"
end
if current_user.update_attribute(:registration_id, nil)
logger.info "Updated registration id attributes to nil"
end
yield
end
end
The problem is that I didn't yield anything for any other controller other than devise:sessions#destroy.
So for those who are as forgetful as me, please remember to think about the other conditions when is_filter_active is not true.
def clear_registration_id_on_destroy_session
is_filter_active = (controller_path == 'devise/sessions' && params[:action] == 'destroy')
if is_filter_active && user_signed_in?
if current_user.update_attribute(:device_platform, nil)
logger.info "Updated device platform attributes to nil"
end
if current_user.update_attribute(:registration_id, nil)
logger.info "Updated registration id attributes to nil"
end
yield
else
yield
end
end
It sounds like your delete link is just acting as a link to the show action, as the method option is not being picked up.
You need to have the appropriate javascript included in your application layout, as the delete link requires JS to use the correct HTTP method.
If you are using Rails >= 3.1 make sure you have the following in the header of the layout file you are using for rendering the page:
<%= javascript_include_tag :application %>
Also make sure you have the csrf_meta_tag in your layout:
<%= csrf_meta_tag %>
Related
I am trying to paginate an array but not able to do so. Please help
Below is my controller code:
require 'will_paginate/array'
class AccountsController < ApplicationController
def children
#account = #rest_resource
#children = []
User.find_all_by_parentId(#account.user.id).paginate(:page
=> params[:page], :per_page => 10).each { |eu|
u = eu.user
ent = Table2.find(u.login)
#children << ent unless ent.nil?
}
end
end
View File -> children.html.erb:
<%= will_paginate #children %>
<table>
<%= render :partial => 'account', :collection => #children %>
</table>
Partial View ->_account.html.erb:
<tr class="<%= cycle('even', 'odd') %> <% if account.user.is_test? %>Test<% end %>">
<td><strong><%= link_to h(account.login), account_path(account) %></strong></td>
<td><% if account.user.test? %>Test <% end %><%= account.attr2 %></td>
<td>
<strong><%= account.companyName %></strong><br/>
<%= account.contact %> - <%= account.Email %> - <%= account.Mobile %>
</td>
<td><%=h account.Status %></td>
</tr>
This is not working. It says:
undefined method `total_pages' for #<Array:0x1041df24>
Rails version:
Rails 3.2.13
JRuby Version:
jruby 9.1.17.0 (2.3.3)
My app is using:
will_paginate (3.0.4)
Please could someone help on this
You are initializing #children as an array and you are passing the same to will_paginate so its throwing an error...try passing like
will_paginate #children[0]
if you wanna pass each and every instance in that array use
#children.each
method
I'm having an issue with image/pdf uploads with ActiveStorage. The images appear to be uploading without issue, but they are causing errors when I try to show them.
My blog model has_one_attached :image and has_one_attached :pdf. The uploads used to work (so I know I have ActiveStorage installed and my amazon s3 set up properly), but something has gone wrong.
The only complicated bit is I need it to work if it has a PDF or not (not all blogs will have a pdf...all should have an image).
My blog#create method is:
def create
#blog = Blog.new(blog_params)
#blog.user_id = current_user.id
if #blog.published
#blog.published_on = DateTime.current
end
respond_to do |format|
if #blog.save
if #blog.image.attached?
#blog.image.purge
end
#blog.image.attach(params[:image])
if #blog.pdf.attached?
#blog.pdf.purge
end
#blog.pdf.attach(params[:pdf])
format.html { redirect_to #blog, notice: 'Blog was successfully created.' }
format.json { render :show, status: :created, location: #blog }
else
format.html { render :new }
format.json { render json: #blog.errors, status: :unprocessable_entity }
end
end
end
My blog#update method is:
def update
if #blog.published
#blog.published_on = DateTime.current
end
if #blog.image.attached?
#blog.image.purge
end
#blog.image.attach(params[:image])
if #blog.pdf.attached?
#blog.pdf.purge
end
#blog.pdf.attach(params[:pdf])
respond_to do |format|
if #blog.update(blog_params)
format.html { redirect_to #blog, notice: 'Blog was successfully updated.' }
format.json { render :show, status: :ok, location: #blog }
else
format.html { render :edit }
format.json { render json: #blog.errors, status: :unprocessable_entity }
end
end
end
My form is simple:
<%= simple_form_for(#blog) do |f| %>
<%= f.error_notification %>
<%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
...
<div class="form-group">
<%= f.label "Blog Image" %><br />
<%= f.file_field :image %>
</div>
<div class="form-group">
<%= f.label "Linked PDF" %><br />
<%= f.file_field :pdf %>
</div>
...
<div class="form-actions text-center">
<%= f.button :submit, class: "btn-outline-primary" %>
</div>
<% end %>
I'm trying to show the image in the blog like this:
<div class="frame" style="background-image: url(<%= rails_blob_url(#blog.image) %>)"></div>
And the PDF like this:
<h2 class="cta text-center"><%= link_to #blog.cta, rails_blob_url(#blog.pdf), target: "_blank" %></h2>
The error I'm getting is signed_id delegated to attachment, but attachment is nil on the place the image is called as a background image on the blog#show page. I get the same error on localhost and Heroku, if it helps.
Finally, I saw this error on this question and did try dropping and recreating my database, but to no avail.
Can anyone see what's going wrong here?
I just ran into this error and really struggled to figure out what could have been happening. It first appeared when I submitted a form and did not include an attachment. Turns out I needed to check to see if something was really attached and deal with that possibility.
Perhaps try moving #blog.pdf.attach(params[:pdf]) to before the respond_to in blog#create
Then, when trying to show the image, maybe you could try something like this
<% if blog.pdf.attached? == false %>
<p>No pdf attached</p>
<% elsif blog.pdf.previewable? %>
<%= link_to(image_tag(blog.pdf.preview(resize: "50x50>")), rails_blob_path(blog.pdf, disposition: "attachment"))
%>
<% elsif blog.pdf.variable? %>
<%= link_to(image_tag(blog.pdf.variant(resize: "50x50")), rails_blob_path(blog.pdf, disposition: "attachment"))%>
<% else %>
<%= link_to "Download file", rails_blob_path(#blog.pdf, disposition: "attachment") %>
<% end %>
Heroku has a good article on active storage here that may also help.
I'm still learning RoR and have followed various tutorials online. In that process I believe I have messed up the nice flash notifications that Bootstrap 2 showed when validating Simple_Form submissions. I have tried to update my code, but without success. Here is what I have so far...
Running:
Rails 3.2.13
Ruby 2.0.0
I just upgraded to Bootstrap 3 using this gem in my gemfile:
gem 'bootstrap-sass-rails'
In my application.html.erb I have:
<%= render 'layouts/messages' %>
In my _messages partial I have:
<% flash.each do |type, message| %>
<div class="alert <%= bootstrap_class_for(type) %> fade in">
<button class="close" data-dismiss="alert">×</button>
<%= message %>
</div>
<% end %>
In my application_helper.rb I have:
def bootstrap_class_for flash_type
case flash_type
when :success
"alert-success"
when :error
"alert-error"
when :alert
"alert-block"
when :notice
"alert-info"
else
flash_type.to_s
end
end
In my users_controller.rb I have:
def update
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'Account successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
And in my edit.html.erb view I have:
<%= simple_form_for(#user) do |f| %>
<%= f.input :firstname %>
<%= f.input :lastname %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.input :password_confirmation %>
<%= f.submit "Save changes", class: "btn btn-lg btn-primary" %>
<% end %>
The validation works, but when returned to the edit view, no formatting (red for errors) or flash message appears. Only a very hard to spot message outside each field is displayed. I must be missing some link between Simple_Form and Bootstrap 3, just don't know what.
I found another post where poster suggested to add:
config.input_class = "form-control"
to my simple_form initializer, but that gave me an error (think I might not have the latest version?):
undefined method `input_class=' for SimpleForm:Module (NoMethodError)
I wish I knew what was going on but I really hope someone can help me get the formatting and flash messages back. Apologies if this is a total newbie question, but I feel a little lost and possibly regretting that I upgraded too soon to Bootstrap 3 maybe.
A thousand thanks in advance to anyone reading all this :)
I got the following mix of code from railscasts.com and other websites.
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name == :notice ? "success" : "error" %>">
<a class="close" data-dismiss="alert">×</a>
<%= msg %>
</div>
<% end %>
Add this to the top of your controller:
respond_to :html, :json
Put this in each controller action:
def create
...
flash[:notice] = 'User was successfully created.'
respond_with(#user)
end
works with rails 3.2+ and 4.0 and twitter bootstrap rails 2, untested in tbsr 3 but will probably work fine.
This worked for me far much better than others as it;s shorter and includes all alert cases -> error, success, alert & notice provided by Bootstrap.
N.B: I renamed your _messages partial to _flash_messages because that is what most people use.
And for those who may be wondering where to generate the _flash_messages partial, it's pretty easy, just right-click your layouts folder in views and 'add new file'. You can call it _flash_messages as I've done, and ensure you have that first underscore (_) before 'flash...'. Tap 'Save'
Now in your _flash_messages.html.erb partial, use this
<% unless flash.blank? %>
<% flash.each do |type, message| %>
<div class="alert <%= flash_class(type.to_s) %>">
<button class="close" data-dismiss="alert">x</button>
<%= message %>
</div>
<% end %>
<% end %>
And in your application_helper.rb use this
def flash_class (type)
case type
when 'error'
"alert-error"
when 'notice'
"alert-info"
when 'alert'
"alert-block"
when 'success'
"alert-success
else
type.to_s
end
end
Then in your application.html.erb, add this as your first line in your first div
<%= render partial: 'layouts/flash_messages', flash: flash %>
Notice that we render the partial (any partial that is), without the 'starter' underscore(_), i.e before the word 'flash..'
You can check out this answer from teamtreehouse on displaying different alert cases.
Hope this helps!
This is a strange error that has really got me bugged. First, some background.
I have the following nested resources in my config/routes.rb:
scope :requirements => { :protocol => 'https' } do
resource :user
resources :orgs do
resources :members
resources :events
resources :levels
resources :attendances
end
resources :sessions, :only => [:new, :create, :destroy]
end
Then, in app/controllers/levels_controller.rb I have:
def edit
#org = Org.find(params[:org_id])
#level = OrgLevel.find(params[:id])
end
def update
#level = OrgLevel.find(params[:id])
if #level.update_attributes(params[:level])
flash[:success] = "Level details updated"
redirect_to #level
else
render 'edit'
end
end
Finally, in app/views/levels/edit.html.erb, I have:
<% provide(:title, "Edit #{#level.name} for #{#org.name}") %>
<div class="hero-unit">
<h2>Edit "<%= #level.name %>" membership level for <%= #org.name %></h2>
<div class="row">
<div class="span6 offset3">
<%= form_for [#org, #level], :url => org_level_path do |f| %>
<%= render 'shared/error_messages' %>
<table class="editor">
<tr>
<td class="label_x">
<%= f.label :name %>
</td>
<td colspan="3">
<%= f.text_field :name %>
</td>
</tr>
</table>
<% end %>
</div>
</div>
</div>
The result of calling https://spot-macbook.local/orgs/55/levels/162/edit is normal, but clicking "Save Changes" results in a redirection to https://spot-macbook.local/orgs/162/levels/162 and the following error:
ActiveRecord::RecordNotFound in LevelsController#show
Couldn't find Org with id=162
Rails.root: /Users/ogod/Projects/rails_projects/nom_de_joye_app
Application Trace | Framework Trace | Full Trace
app/controllers/levels_controller.rb:71:in `correct_user'
Request
Parameters:
{"requirements"=>{"protocol"=>"https"},
"org_id"=>"162",
"id"=>"162"}
Note that the org_id has changed to "162" instead of "55". What am I doing wrong?
Doh!
Five seconds after I post this question, I realised there error and corrected it.
The original has the update method with the following:
redirect_to #level
This should be:
redirect_to org_level_path(#org, #level)
Such a simple error, but I was looking in the wrong place!
I'm relatively new to rails and am trying to pull off my first polymorphic association with comments.
I am running rails 3.2.3
Edit - When I try to post a comment, my log is returning this error:
Started POST "/comments" for 127.0.0.1 at 2012-05-20 13:17:38 -0700
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"SOLcF71+WpfNLtpBFpz2qOZVaqcVCHL2AVZWwM2w0C4=", "comment"=>{"text"=>"Test this comment"}, "commit"=>"Create Comment"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 101 LIMIT 1
Completed 500 Internal Server Error in 126ms
NoMethodError (undefined method `Comment' for nil:NilClass):
app/controllers/comments_controller.rb:13:in `create'
I have tried out many different solutions offered on SO and elsewhere, including the answer from Jordan below, due, I'm sure, to my own inexperience, but have been unable to resolve the error.
The trace calls out line 13 in the Comments Controller and I commented after that line below to mark the error:
class CommentsController < ApplicationController
def index
#commentable = find_commentable
#comments = #commentable.comments
end
def new
#post = Post.find(params[:post_id])
end
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment]) #<<<<LINE 13
if #comment.save
flash[:notice] = "Successfully created comment."
redirect_to :id => nil
else
render :action => 'new'
end
end
private
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
end
Posts Controller:
def show
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #post }
end
end
Comment template (in post show)
<ul id="comments">
<% if #comments %>
<h2>Comments</h2>
<% #comments.each do |comment| %>
<li><%= comment.text %></li>
<% end %>
<% else %>
<h2>Comment:</h2>
<% end %>
</ul>
<%= simple_form_for [#commentable,Comment.new], :html => { :class => 'form-horizontal', :multipart => true } do |f| %>
<fieldset>
<%= f.input :text %>
Upload Photo <%= f.file_field :photo %>
</fieldset>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
</div>
<% end %>
Post show:
<p id="notice"><%= notice %></p>
<div class="row">
<div class="span2 offset1">
<%= image_tag #post.photo.url(:show) %>
</div>
<div class="span5">
<h1><%= #post.title %></h1>
<p><%= #post.index_text.html_safe %></p>
<p><%= #post.show_text.html_safe %></p>
<%= render "comments/comment" %>
<%= render "comments/form" %>
<% if can? :update, #course %>
<%= link_to 'Edit Post', edit_post_path(#post), :class => 'btn btn-mini' %>
<%= link_to 'Delete Post', #post,
confirm: 'Are you sure?',
method: :delete,
:class => 'btn btn-mini' %>
<%= link_to 'New Post', new_post_path, :class => 'btn btn-mini' %>
<% end %>
</div>
<nav class="span2 offset1">
<ul class="well">
<li>Category 1</li>
<li>Category 2</li>
</ul>
</nav>
</div>
<div class="row offset2">
<%= link_to 'Back to Posts', posts_path, :class => 'btn btn-mini' %>
</div>
Routes:
resources :posts, :has_many => :comments
resources :comments
It is probably something obvious that someone with more experience can resolve. Let me know if anything comes to mind. Brian
The problem is that #commentable is nil, which means that CommentsController#find_commentable is returning nil. I think your regular expression is sound, so that means one of two things is happening in find_commentable:
There aren't any keys in params that match your regex.
Your regex is matching but there aren't any records in the resulting table with the id in value.
Debug this as usual by inspecting params and the records in your database to make sure they look like you expect them to look.
The problem is your find_commentable method.
Here are the params passed to your CommentsController#create:
Started POST "/comments" for 127.0.0.1 at 2012-05-20 13:17:38 -0700
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"SOLcF71+WpfNLtpBFpz2qOZVaqcVCHL2AVZWwM2w0C4=", "comment"=>{"text"=>"Test this comment"}, "commit"=>"Create Comment"}
Here is your CommentsController#create:
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment]) #<<<<LINE 13
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
As you can see, find_commentable expects a param like xx_id (for example, comments_id) which it uses to search for an appropriate class (in case of comments_id, it will be Comment), otherwise it returns nil. Refer classify and constantize here.
Your params do not contain any such param. So, you always get a nil object.
Your find_commentable needs some rework. I think in case of nested_fields, it should be an expression like
/(.+)_attributes$/
instead of
/(.+)_id$/.
And you need to have
:accepts_nested_attributes_for :commentable
in your Comment model class.
I tried both of the above answers, but the problem continued.
I ended up consulting with a friend who suggested the following solution, which I like because it's more elegant than my original attempt and easier to read (for later, when I or someone else need to return to the code):
def find_commentable
if params[:post_id]
Post.find(params[:post_id])
#elsif params[:other_id]
# Other.find(params[:other_id])
else
# error out?
end
end
The commented out section will refer to other associations once I get them up and running.