removing a document by passing its id using form_tag - ruby

Let's say I have book model, book.rb
class Book
include Mongoid::Document
field :book_id, type: String
field :title, type: String
end
(Here I'm using mongoid, but I think for this question it doesn't matter what type of data is.)
The book model has its own controller, views, etc.
Now, I want to create a page with form_tag (let me know if this is not a proper way), where by entering book's id and clicking enter I'll be able to remove the record this this given id from the database.
remove.html.erb:
<%= form_tag books_path, :method => 'get' do %>
<p>book_id:
<%= text_field_tag :book_id, params[:book_id] %>
<%= submit_tag "Remove", :name => nil, :confirm => "Are you sure?" %>
</p>
<% end %>
I know how to remove a given document, but can't figure out how to pass the value entered in the form and where to put the logic that will remove document.

First things first. Why do you need to store a book_id for your Book model ? Mongoid already provide a _id field for this purpose.
The usual way to destroy resources is to hit the destroy action in your controller by making a DELETE HTTP request.
class BooksController
def destroy
Book.find(params[:id]).destroy
redirect_to :back
end
end
Then simply do a link with the following:
link_to "Delete", book_path(#book), method: :delete
Where #book is your book instance.

Related

redirect to another URL using submit button in ruby

I have submit button and i want to redirect in another URL (hard coded) this URL
https://www.ccavenue.com/shopzone/cc_details.jsp
my code :
<%= form_tag #ccavanue do |f| , url => "https://www.ccavenue.com/shopzone/cc_details.jsp", :html => :method => "put" %>
<%= hidden_field_tag :my_field, #MerchantId, :id => 'merchant_id' %>
<%= submit_tag "Click Me" %>
<% end %>
i want to redirect another website URL with this submit button . please guided me.
Change your code to following:
<%= form_for #ccavanue, url: "https://www.ccavenue.com/shopzone/cc_details.jsp" do |f| %>
<%= f.hidden_field :my_field, #MerchantId, :id => 'merchant_id' %>
<%= f.submit "Click Me" %>
<% end %>
In Rails a form is designed to create or update a resource and reflects the identity of the resource in several ways:
The url that the form is sent to (the form element's action attribute) should result in a request being routed to the appropriate controller action (with the appropriate :id parameter in the case of an existing resource),
Input fields should be named in such a way that in the controller their values appear in the appropriate places within the params hash, and
For an existing record, when the form is initially displayed, input fields corresponding to attributes of the resource should show the current values of those attributes.
In Rails this is achieved by creating form using form_for where:
If we want to create any object we use POST method within url and PUT method if we are trying to update an existing record.
Rails framework is smart enough to use POST or PUT method by itself looking at the url of the form. So in this case we need not use method parameter within form_for url.
Probably you can start with Michael Hartl's tutorial

Not showing created blog entries

I'm fairly new to Rails and learning to create a blog using this tutorial. On step 10, once I define create and show, after creating a new post in browser I don't see any entries on show with id page. All I see is heading and and blank title and post header.
Following is my controller -
class PostController < ApplicationController
def index
end
def new
end
def create
#post = Post.new(params[:posts])
#post.save
redirect_to #post
end
def show
#post = Post.find(params[:id])
end
end
Show view ---
<h1>Show a post</h1>
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<p>
<strong>Text:</strong>
<%= #post.text %>
</p>
Route ---
RailsBlog::Application.routes.draw do
resources :post
root :to => "post#index"
end
Form ---
<%= form_for :post, url: {action: 'create'} do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit 'Submit' %>
</p>
<% end %>
May be this is just a spelling mistake, but since I've recently started learning Rails, I'm unable to resolve this.
Update: I can go to particular id using
http://localhost:3000/post/1
but am only seeing blank page with view headers
The problem is here:
#post = Post.new(params[:posts])
It should be params[:post] - singular, not plural.
Also note that the best practice with form_for is to pass an object instead of symbol:
form_for #post do |f|
Then:
You don't need to specify url
You can reuse the same form for an edit action or create action (if object creation failed due to failing validation)
This however requires to initialize new object in your new action:
def new
#post = Post.new
end
UPDATE:
Also your routes are incorrect. When defining plural resources, you need to use plural form (it's more the convention than requirement, but since you're learning stick with it). So change your routes to:
resources :posts
And rename your controller to PostsController (remember to rename file name as well). restart the server and all should work.
ANOTHER UPDATE:
You also need to rename folder app/views/post to app/view/posts.
AND YET ANOTHER UPDATE:
In rails 4, you are not allowed to mass assign any params which has not been whitelisted using strong parameters. You need to tell rails which fields you allow to be assigned first - this is a security thing. You need to make some changes to your controller:
class PostsController < ApplicationController
...
def create
#post = Post.new(post_params)
...
end
...
private
def post_params
params.require(:post).permit(:title, :text)
end
end
This is the way to tell your controller that you are expecting those attributes from your form and they can be safely assigned.
I had just similar problem on the same tutorial.
The code spelling was correct and clearly accorded to examples in tutorial and BroiSatse's answer above.
The mistake was in order of private method definition.
How it was:
...
private
def post_params
params.require(:post).permit(:title, :text)
end
def show
#post = Post.find(params[:id])
end
...
The working order:
def show
#post = Post.find(params[:id])
end
private
...
Anyway, this topic was rather helpful. Thak you for your answers!

Rails 4 - Controller Edit Action Returning Wrong Record

I have a Comment model which belongs to both User and Story. Creating a comment correctly associated to the appropriate User and Story is working fine but when trying to edit the comment my edit action appears to retrieving the wrong record.
The offending action in comments_controller.rb:
def edit
#story = Story.find_by(params[:story_id])
#comment = #story.comments.find_by(params[:id])
end
The link used to render the comments/edit view:
<%= link_to 'edit', edit_story_comment_path(comment.story_id, comment.id) %>
The corresponding view:
<%= form_for(#comment, url: { controller: 'comments', action: 'update' }) do |f| %>
<%= f.text_area :content %>
<%= f.submit "update" %>
<% end %>
The edit view appears to be rendering the most recently added comment regardless of which #comment I am trying to edit.
You're using find_by, which is basically a magic find_by_X method, with no fields specified. find_by(1) generates invalid SQL for me using Postgres, but it might be that whatever database back-end your using accepts it.
Regardless, find_by certainly won't do what you want it to do.
You should be using find, if you want to find records by id:
#story = Story.find(params[:story_id])

How to call an `f.action` to a custom :delete callback in an Active Admin form

In order to remove (paperclip) images from my objects, I have a custom callback (and route) defined:
ActiveAdmin.register Camping do
#...
member_action :destroy_image, :method => :delete do
camping = Camping.find(params[:id])
camping.image.destroy
redirect_to({:action => :show}, :notice => "Image deleted")
end
end
This works as expected; trough a named route destroy_image_admin_camping => /admin/campings/:id/destroy_image.
The problem is that I cannot find how to add this to the form:
ActiveAdmin.register Camping do
form do |f|
f.inputs "Camping" do
f.input :name
f.input :image
f.action :delete_image, :url => destroy_image_admin_camping_path(#camping.id), :button_html => { :method => :delete }
f.input :description
end
f.actions
end
#...
end
More detailed: I don't know how to pass the "id of the current item we are editing" into destroy_image_admin_camping_path; #camping is nil, f.camping not defined and so I don't know how to pass the item in there.
Is this the right approach? I prefer this "ajax-ish" interface over a more common checkbox-that-deletes-images-on-update, but I am not sure if this will work at all.
There's a few questions here, I'll try to address them all.
How to access the "id of the current item we are editing"
You are pretty close in looking for f.camping. What you want is f.object, so:
destroy_image_admin_camping_path(f.object.id).
NOTE: f.object.id will be nil when it's a new form (as opposed to an edit form), you'll want to check for that with unless f.object.new_record?
"Is this the right approach?"
I'm not sure, really. To me it seems like making requests without actually saving the currently rendered form could create complications, but it might turn out to be a better interface. Anyway, if you want to do the checkbox-that-deletes-images-on-update, this should help you out: Rails Paperclip how to delete attachment?.
However, if you want the ajax-ish approach I think you'll want an <a> tag styled as a button. The problem with actually using a button is that you don't want to submit the form.
Here's an example:
f.inputs do
link_to 'Delete Image', delete_image_admin_camping_path(f.object.id), class: 'button', remote: true, method: :delete
end
remote: true will make it an ajax request and ActiveAdmin gives you a pretty reasonable button class for <a> tags. Updating the interface based on success / failure is left as an exercise to the reader.
Also, you'll probably want to use erb templates for this instead of the Active Admin DSL (see http://activeadmin.info/docs/5-forms.html at the bottom).
Like this:
# app/views/admin/campings/_form.html.erb
<%= semantic_form_for [:admin, #post] do |f| %>
<%= f.inputs do %>
<%= f.input :name %>
<%= f.input :image %>
<%# Actually, you might want to check for presence of the image, I don't know Paperclip well enough to demonstrate that though %>
<% unless f.object.new_record? %>
<%= image_tag f.object.image_url %>
<%= link_to 'Delete Image', delete_image_admin_camping_path(f.object.id), class: 'button', remote: true, method: :delete %>
<% end %>
...
<% end %>
<%= f.actions %>
<% end %>

Rails: Ajax-enabled form without a model object

I'm new to Rails and having a hard time figuring out how to create a form that submits over Ajax without having a corresponding model object.
My use case is a simple form that collects an email address and sends it an email; there's nothing to be persisted, so no model.
In cases where I do have a model, I've had success with form_for(#model, remote: true). I can't seem to find the right helper for the case where there is no model. I tried form_tag(named_path, remote: true) and that works, but does not use Ajax.
Pointers to an example with an example with a proper controller, .html.erb and routes.rb would be really appreciated.
Here's how I solved it. The key was using form_tag and specifying a hash with an argument that properly matched my route. For my business logic, I need to pass in an "id" param, which is used in the controller logic.
<%= form_tag(sendmail_path({ id: 1}), remote: true) do %>
<%= text_field_tag :email, params[:email] %>
<%= submit_tag "Send", remote:true %>
<% end %>
routes.rb:
MyApp::Application.routes.draw do
post '/sendmail/:id(.:format)' => 'mycontroller#sendmail', :as => 'sendmail'
# etc...
end
I also had to supply a sendemail.js.erb template which updates the form after submission.

Resources