form_tag calling an instance of a class on the controller - ruby

I am trying to use a form_tag on a Rails application that, when submitted, call an instance of a class on the controller.
View
form_tag '/order', method: :get
select_tag 'type', options_for_select(#options_for_type, #type)
text_field_tag 'numbers', nil, placeholder: "100"
submit_tag "Get Info"
controller
def order
#order = Order.new(params_here).fetch_info
#type = params[:type] || "type1"
#options_for_type = [["type1", "type1"], ["type2", "type2"]]
...
end
This class sends some API requests (JSON).
Now problem is, I am getting an error from the API that some parameters are missing, which is expected since I haven't submitted the form with all the params, but it seems the class is called automatically when the page is loaded. I would have expected the class to be called only when the submit button is pressed?

Can you make the form_tag sort of a block? Like:
form_tag '/order', method: :get do
# All form elements
end
Maybe displaying your route here can also help.

Related

Preview Post before save in active admin

I am looking for some pointers on getting started with this feature; I would like a user to be able to preview what their post would look like if saved
ActiveAdmin.register Post do
permit_params :comments, :title, :category_id, :slug, :published
# Create Blog Post
form do |f|
inputs 'Blog' do
f.semantic_errors
f.input :title
f.input :category_id, as: :select, collection: Category.all
f.input :comments, as: :text, input_html: { rows: 10, cols: 10 }
f.input :published, as: :boolean
end
inputs 'Submit' do
f.actions
end
end
end
So looking at the active admin documentation I can see you can add custom action items
action_item :preview, only: :new, name: 'preview_button' do
# do stuff here
end
I can also add a custom controller action in the form of a collection_action which will also add a route for me
collection_action :preview, method: :post do
#post = Post.new(params[:post])
end
So now I have a custom action preview and a button that can pass data to the method (I have hard coded it for now, as unsure how to get the data from outside the form).
This is what I have so far:
action_item :preview, only: :new, name: 'preview_button' do
link_to 'Preview', preview_my_admin_panel_posts_path(post: { title: 'Test Title', comments: 'test comments', category_id: '1' })
end
# Add controller action
collection_action :preview, method: :get do
#post = Post.new(params[:post_params])
end
My view gets rendered but nothing gets outputted, how do I then show the data?
Is this the correct approach?
Update
Can now show the hardcoded data with
collection_action :preview, method: :get do
#post = Post.new(permitted_params[:post])
end
The difference being in the active admin docs
The permit_params call creates a method called permitted_params. You should use this method when overriding create or update actions:
Now I just need to grab the form data outside the form and pass it through my link_to and then be able to keep the form populated with the same data if I go back to the form.
Ideally I would like to have the preview button within the f.actions as then I would have access to the #post object.

Get Rails to hit controller with an input tag submit

View:
%input{type: 'submit', action: 'home#create_user'}
Controller:
class HomeController < ApplicationController
def index
render 'home/index'
end
def sign_up
render 'home/sign_up'
end
def create_user
render 'dashboard/dashboard'
end
end
routes.rb
post 'home/create_user' => 'home#create_user', :as => :create_user
Why is this button not hitting the controller?
By itself, an submit tag isn't going to generate the form. I tried your code above and the button doesn't do anything. Unless I'm forgetting INPUT doesn't have an ACTION attribute.
If you had a link to that page, the reason it's not working is because by default that link will be a GET request and you've restricted the route to POST.
So, either wrap it up in a form or use button_to or the :method => :post solutions to make it POST the request and it should work.
Something like this:
= button_to 'click me', create_user_path
= link_to 'click me', create_user_path, method: 'post'

removing a document by passing its id using form_tag

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.

Routing Error - No route matches

Here's the problem, when visiting requests/index.html.erb:
Routing Error
No route matches {:action=>"cancel", :controller=>"requests"}
index.html.erb:
<%= link_to "Cancel", cancel_request_path %>
routes.rb:
resources :requests do
get 'cancel', on: :member
end
requests_controller.rb:
def cancel
request = Request.find(params[:id])
request.update_attributes(stage: "Cancelled")
redirect_to root_path
end
What am I missing?
Fixed. I just needed to change to this in my index.html.erb:
<%= link_to "Cancel", cancel_request_path(request.id) %>
I thought all the attributes of the object would get passed to the action in params, but I guess I have to specify which params to pass to the action.
get 'cancel', :on => :member
On member means, you path would be like :
cancel_requests_path(:id=>request_id)
or simply the requests object in the parameter...

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