Rails button_to with image and actions - ruby-on-rails

I want to show button with image.
I have this code
<%= image_submit_tag "down.png", controller: "posts", action: "votedown", post_id: post.id, topic_id: post.topic_id, class: "xta" %>
Its visible properly but not calling action "votedown"
In my routes I have
post '/votedown', to: 'posts#votedown
Please also suggest if there is any other way to call the method votedown with params and image "down.png"

image_submit_tag must be used in conjunction with a form - it works just a normal html <input type="submit"> button.
You might also want to change your route definition into something more restful:
patch '/posts/:id/votedown' => "posts#votedown", as: 'votedown_post'
This makes it more apparent that this route acts on a post - and we use the PATCH method since we are changing a resource instead of creating a new resource.
Armed with our new route we can simply create a form:
<%= form_for(#post, url: votedown_post_path(#post) ) do |f| %>
<%= image_submit_tag "down.png", class: "xta" %>
<% end %>
Note that you do not need to add an input for the post id since it will be available as params[:id].
Another way to do this would be to use Rails unobstructive javascript driver to create a link or button which sends a PATCH request to '/posts/:id/votedown'.
<%= link_to image_tag("down.png", class: "xta"), votedown_post_path(#post), method: :patch %>

Related

POST Routing Issue for Custom Form

I have added a custom route, custom controller code, and actioned the custom route in the form, but I get an error regarding the route, even as it shows the route in error message.
The form/view is as follows:
views/survey_request/confirmation.html.erb
<%= form_for #survey_request, url: survey_requests_confirm_path do |f| %>
<p>Your Email Address: <%= f.text_field :customer_email %></p>
<%= f.hidden_field :survey_token, value: #survey_request.survey_token %>
<p>Your survey token: <%= #survey_request.survey_token %></p>
<p><%= f.submit %></p>
<% end %>
My relevant routes in the routes.rb file are as follows:
get 'survey/:id', to: 'survey_requests#confirmation'
put 'survey_requests/confirmation', to: 'survey_requests#confirmation'
put 'survey_requests/confirm', to: 'survey_requests#confirm'
In the survey_requests_controller.rb I have a method defined
def confirm
#code here to confirm the users email and token
end
When I run the app, the confirmation.html.erb form shows up fine, to include the token passed to it. When I submit the form I get the following error:
No route matches [POST] "/survey_requests/confirm"
However when I scroll down on the same error page, it shows the route:
survey_requests_confirm_path PUT /survey_requests/confirm(.:format) survey_requests#confirm
Any suggestions? Thanks!
The problem is that the defined route uses a PUT method and the form route uses a POST method.
Either change the route to be POST with post 'survey_requests/confirm', to: 'survey_requests#confirm' or add method: :put to the form form_for #survey_request, url: survey_requests_confirm_path, method: :put so the methods match.

Publish method doesn't work properly

I have an Entry model with a boolean column published, which is set to false by default. I wrote the following method in the model:
def self.publish
self.update(published: true)
end
and in my controller I have
def publish
#entry = Entry.find(params[:id]
#entry.publish
redirect_to entries_path
end
(I thought to make it similar to the calling of destroy method in the model). Finally, in my view I have this:
<%= link_to "Publish", entries_path, method: :publish %>
But when I click the link, the request is processed by create method and returns me the following error:
ActionController::ParameterMissing in Multiflora::EntriesController#create
param is missing or the value is empty: entry
The method is wrong in link_to as per the API so you have to mention one of valid Http methods (patch preferred in your case) , and then edit your route.rb file to transfer this patch request to your specified function like this:
patch'/entries/publish', to: 'entries#publish'
then change the "entries_path" to "entry_path"
so link code should look like this:
<%= link_to "Publish", entry_path, method: :patch%>
First thing, there is no HTTP method called :publish it should be :put or :patch
Second you need to pass id as parameter
<%= link_to "Publish", publish_entry_path(#entry) %>
Also you will need to add route for publish action
resources :events do
member do
put :publish
end
end
publish method should be instance method
def publish
self.update(published: true)
end
Thanks for all the answers, I've figured out what was my mistake, but I took a little think and decided to make it much more simple: I just added a checkbox to edit form, that sets :published attribute of entry true. Here it is:
<%=form_for(#entry, as: :entry, url: content_entry_path(#entry)) do |f| %>
# ...
<p>
<%= f.label "Publish" %> <br />
<%= f.hidden_field :published, value: '' %>
<%= f.check_box :published, checked: true %>
</p>
<% end %>
Anyways a lot of thanks for your answers! That was my lack of knowledge and I'll remember what have I done wrong

Rails - How to invoke methods upon submission of form_tag?

I have a Rails Controller, with methods for new and create. This is where I have my main form, and I know how these actions work.
I also created another view with a smaller one field form. I would like to perform an action if a user clicks submit on this form.
I created a route with get and post actions
match "/redemption", to: "accounts#redemption", via: [:get, :post]
In my accounts#new action, users can purchase an account. They are given a redemption code.
I decided to make a new view, where if they already have a code, they can enter it.
The logic will be fairly easy for me, but I need to know how I can perform an action on this.
Here is the form, I want to perform an action on
<%= form_tag('/redemption') %>
<%= label_tag 'Enter your Redemption Code' %>
<%= text_field_tag 'Redemption Code' %>
<%= submit_tag("Redeem") %>
I'm not sure how I can do this, since it doesn't involve the new and create actions. They are reserved for a different purpose.
You need to have your form declare a block and place your submit tag inside it. This will make it so the button posts to your redemption action. Then you would just access the params hash like normal.
<%= form_tag('/redemption') do %>
<%= label_tag 'Enter your Redemption Code' %>
<%= text_field_tag :redemption, 'Redemption Code' %>
<%= submit_tag("Redeem") %>
<% end %>
and then in your AccountsController
def redemption
call_redeem_action params[:redemption]
end
you can also name your route if you want..
match "/redemption", to: "accounts#redemption", via: [:get, :post], as: :redemption
and then your form would be
<%= form_tag redemption_path do %>
which I find easier, since if you ever need to rename that the uri, you can just adjust it in once place.
submit_tag calls the action specified by the form_for, if no action is specified then it will default to the current action, which in this case is 'redemption' as Doon states below. So using :action => 'your action' would probably be more clear. More info here.

Rails Call Custom Controller Action from Custom Form

In a Rails project, I have the following controller action for the controller exchanges.rb:
def update_ordid
# Get the active exchange
#exchange = Exchange.find(params[:id])
# Decide which order ID field to update
active_order_field = params[:ordfld]
# Save the order ID
order_id = params[:ordid]
if active_order_field == 1 then
#exchange.order_id_1 = order_id
else
#exchange.order_id_2 = order_id
end
#active_exchange.save
respond_with(#exchange)
end
I've set up a route to this controller action:
resources :exchanges do
collection do
get 'update_ordid'
end
end
I want to call this action that accepts an order ID from a form on an exchanges show.html.erb page. I need to pass three values:
The ID of the current exchange, such as the integer in this example URL localhost:3000/exchanges/2 (This is the page the form is on)
The order ID as input from a text-field
Which of the two possible exchange fields the action should update
Next I need to create a custom form which will pass these values as parameters to the action. I haven't been able to find a good tutorial on how to do this yet, but my first thought was to set up the following:
<%= form_for(#exchange) do |f| %>
<div class="field">
<%= f.label :ordid, "Order ID" %><br>
<%= f.text_field :ordid, class: "form-control" %>
</div>
<% if #isrequestor == true %>
<%f.hidden_field :ordfld, :value => "1" %>
<% else %>
<%f.hidden_field :ordfld, :value => "2" %>
<% end %>
<div class="actions">
<%= f.submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>
This gives me a NoMethodError stating the method 'ordid' is undefined. I'm guessing I need to modify the first line of code to associate the form with the custom action I've set up, but have no idea how to do so properly.
Yah, I got your point. So you wanted the following thing:
You wrote an custom action
You wanted to submit a form that action
You have registered your action in the router.
So let me answer the following solutions and find some mistakes you made in your code.
# in route.rb
resources :exchanges do
patch :update_ordid, on: :member # this is the best practice I would say,
#when you are trying to modify an existing record. So this action will only
#be reached with patch http methods
# on :member action an parameter id is required.
end
now if you generate your routes by running:
bundle exec rake routes
you will see a path like:
update_ordid_exchange /exchange/:id/update_ordid # :id parameter for exchange record
in your form set the url:
<%= form_for(#exchange, url: update_ordid_exchange_path) do |f| %>
or
<%= form_for(#exchange, url: url_for(controller: :exchange, action: update_ordid)) do |f| %>
Now then you will this form can submit this values within the parameter in your desire field.
So let me summarize things up here:
1. Setup your route properly
2. Check the url based on your route by generating rake routes command as shown above
3. Set the proper url and check if http method is correctly define in your form helper. For member actions, form helper by default use patch as http method. you just have to set the url.
Hope you understand my flow.

How do you post a value from a form_tag?

If you have a post action to "do_something/:id" => :start (say with a named route 'start'), how do you create a form_tag that submits the :id based on a select_tag selection by the user ?
Assuming you aren't using resources.
The issue is that you have a post action, however you want to set a GET variable via a form submission(that has to use POST).
You can make the form make a GET request, like so:
<%= form_tag(start_path, :method => "get") do %>
<%= select_tag "id", "<option>1</option><option>2</option><option>3</option><option>4</option>" %>
<% end %>

Resources