Rails 3.2 button_to not passing GET variable - ruby-on-rails

still learning rails, doing my first project.
i'm trying to pass an additional "category" variable to "new" method in my "pages" controller
def new
#page = Page.new
#cats = Cat.all
end
i'm doing it so the new page has already selected category from dropdown menu
it works when i use link_to
<%= link_to "Create new page", new_page_path(:cat => #cat.id) %>
but when i'm trying to use button_to
<%= button_to "Create new page", new_page_path(:cat => #cat.id), method: :get %>
the variable "cat" is not passed to "new" action view. it's not a big problem but it screws up my layout because i'm using button_to in all other places and i just hoped there is a better way to solve it that adding more css so it'll look the same

One possible way to solve this is to create a form with a hidden field
<%= form_tag new_page_path(), :method => :get do
hidden_field_tag "cat", #cat.id
button_to "Create new page"
end %>
Your version doesn't work because "button_to" method creates a form which passes params to the browser only from input fields.

Related

Match button click to new rails controller method inside a form tag

I've got a form_tag and an existing submit_tag that maps to a rails controller method. My .haml code is shown below:
.form-group
=form_tag "/set_limits", {id: 'ec2-instance-limit-form'} do |form|
= submit_tag "Increase Limits", {class: "btn btn-danger"}
A snippet of my routes.rb file matching the url /set_limits to a method of a rails controller is shown below.
match '/set_limits', to: 'limits#handle_limit_request', via: [:post]
I now added a button on the same page.
%button.btn.btn-info(id="customer-status" type="button") Customer Status
However when I click this button the request still routes to the handle_limit_request method. I would like the action of clicking this button to route to a new method via POST, say limits#check_customer_status. How do I route the button click to a new controller method while ensuring that the action of clicking the submit_tag still routes to limits#handle_limit_request?
I would like the action of clicking this button to route to a new
method via POST, say limits#check_customer_status
In order to do so, use button_to
= button_to "Customer Status", '/check_customer_status', :method => :post, :form_class => "btn.btn-info", id: "customer-status"
Note - Position of this button (Customer Status) on the page should be outside of form_tag scope, as button_to internally generates a form also, form within a form may not work.
According to me the best way may be to handle this in controller itself other then routes or from passing different url to form_for.
.form-group
=form_tag "/set_limits", {id: 'ec2-instance-limit-form'} do |form|
= submit_tag "Increase Limits", {class: "btn btn-danger", name: "increase_limits"}
= submit_tag "Customer Status", {class: "btn btn-danger", name: "customer_suport"}
Then in limits controller,
def handle_limit_request
if params[:increase_limits]
# Do stuff for first button submit
elsif params[:customer_suport]
your code for method "check_customer_status"
or
render check_customer_status
end
end

Rails add dynamic attribute on data content helper link

i need to get a ajax tooltip on a dynamic link, so the logic seems to concatenate it. but, still not work, so, someone know a way to do this?
thank's
<%= link_to "Profile", edit_user_path(current_user), :class =>"ttooltip", :data => {:url => "/users/#{#current_user}/links"} %>
You're string interpolating the current user object, which will call .to_s on the user object, which probably isn't what you want.
If links is nested under each user, you typically follow the 'users/:id/links' so you need to interpolate the id instead of the user object like so:
<%= link_to "Profile", edit_user_path(current_user), :class =>"ttooltip", :data => {:url => "/users/#{current_user.id}/links"} %>
(Where current_user is a helper method that returns the current_user object.)

How to access a single, visible element from an array of objects being displayed by will_paginate?

I am working on a rails web app which manages students and courses. I have a courses controller which has the following index action:
def index
#courses = Course.paginate(:page => params[:page], :per_page => 1)
#courses.order(:startDate)
##thisCourse = Course.find(params[:page])
end
So pretty standard except for one thing - all the details of a single course are shown on one page and to show the details of the next course, you move to the next page of the pagination.
The problem is that in this index page showing the details of 1 course per pagination, I have a "Sign Up!" button which when pressed needs to create a a new record in the 'signups' db table which has the automated 'id' field and then the 'user_id' and the 'course_id' fields.
The 'user_id' is easy to find (current_user.id).
The 'course_id' is proving difficult. I imagine that pressing the Signup button should send the course_id to the signups_controller where a create function can do the work. But how can I get this exact course ID from the index page to the signups_controller's create action?
As you can see in the code I pasted from the courses_controller's index action,the '#thisCourse' variable has been commented out because I have found no way to define which course is currently being shown on the page.
The fields are rendered by the will_paginate Gem so I'm not sure how it's generating the fields but I was thinking that maybe I could create a named hidden field which includes the course_id and use that when the sign up button is pressed, however I'm not sure how to go about it.
Does anybody have any ideas?
Thanks!
Well, you can use show method (output one course) instead of index(output all courses) method, that will always get your course id through params.
Basically I changed my approach to the problem. I removed the button which was supposed to call the signups_controller and create the new record in the signups table. This button was replaced by adjusting the form_for helper so that it's submit button would send all the necessary data to the signups_controller (including the id value which was added to the form as a hidden field).
The form ended up looking like this:
<%= form_for course, :url => {:controller => "signups", :action => "create"}, :method => "post" do |f| %>
<%= hidden_field_tag :course_id, course.id %>
<%= f.label :"Course Title" %>
<%= f.text_field :courseTitle, class: 'form-control' %>
+ all fields included in the form....
<%= f.submit "Sign Up!", class: "btn btn-primary" %>
<% end %>
This parameter of form_for defines which controller and which action in that controller is the submission target:
:url => {:controller => "signups", :action => "create"}
and this parameter overwrites the default http action (default is PATCH but in this case I wanted to POST i.e. create a new entry in the signups table):
:method => "post"
I'm not sure if this is a very quick and dirty solution but technically it gets the necessary data to the correct destination controller.

Rails onclick => 2 items

The following works great for carrying forward data from one page to another:
<%= link_to 'New Work Order', new_workorder_path, :class => 'btn btn-primary', :onclick => session[:worequest_id] %>
How would I add a 2nd field? The following doesn't work:
<%= link_to 'New Work Order', new_workorder_path, :class => 'btn btn-primary', :onclick => session[:worequest_id] = #worequest.id, [:client_id] = #worequest.client_id %>
Thanks!
UPDATED
This is the code I'm using in the new work order form. It picks up the worequest_id field from the session
<% if session[:worequest_id] != nil %>
<%= f.hidden_field :worequest_id, :value => session[:worequest_id] %>
onclick doesn't really work this way – it's an html attribute used to store JavaScript code to be executed when the element is clicked. While you can use it to evaluate Ruby code in the context of a Ruby method call (in this case as part of the options hash given to link_to), it doesn't really make sense to do so.
In your first example, it doesn't actually do anything. If you check your rendered html on the page where that link appears, I expect it evaluates to something like New Work Order. You can, however, store data in session (which is persistent for as long as the user remains logged in), which is why you're seeing this data carrying forward from page to page.
If you're trying to fill in default values for the new workorder, you could pass them as params to the path method:
link_to 'New Work Order',
new_workorder_path('workorder[worequest_id]' => #worequest.id,
'workorder[client_id]' => #worequest.client_id),
:class => 'btn btn-primary'
In your workorders#new action, your model instantiation would need to include the params:
def new
#workorder = Workorder.new(params[:workorder])
end
However, this might not be the best way to proceed. If there will always be a client or worequest associated with a workorder, you might want to look into nested routes.

Rails 3 - Forms, Custom Submit Button based on Action?

I currently have a couple of forms that I'm trying to change the button that submits it based if I'm on the edit or new action. I had two forms created but this smelt bad, and am now just using a single form partial.
At the end of my partial, I have something like this at the end of my forms:
<p>
<% if controller.action_name == 'new' %>
<%= f.submit "Create", :class => "pink_button"%> or
<% elsif controller.action_name == 'edit' %>
<%= f.submit "Update", :class => "pink_button"%> or
<% end %>
<%= link_to "cancel", :back %>
</p>
That way, if I'm creating some new, the button reads "Create", and if it's an update that a user is trying to complete, the button reads "Update". This works great, until the form is submitted and validation fails.
In my controller, I'm catching things that do fail like so:
def update
#list = current_user.lists.find(params[:id])
if #list.update_attributes(params[:list])
redirect_to list_path(#list), :notice => "List '#{#list.name}' updated."
else
render :action => 'edit'
end
end
So the form is simply re-rendered. The problem is, I'm no longer on the edit path. This means, my form button does not show up any longer.
Is there a convention to what I'm trying to do?
Thanks
Yes, this is handled in Rails with i18n by default. The translations are in ActionView, and look like this:
en:
helpers:
select:
# Default value for :prompt => true in FormOptionsHelper
prompt: "Please select"
# Default translation keys for submit FormHelper
submit:
create: 'Create %{model}'
update: 'Update %{model}'
submit: 'Save %{model}'
All you need to do is f.submit (without passing "Create" or "Edit", etc) and the translations will do the rest. You can overwrite these by dropping the above yaml into your local locales.
If you need to set the class you can pass nil, e.g. f.submit nil, :class => 'whatev'
The Rails way is to check if the record is new or not:
#list.new_record? ? "Create" : "Update"
Rails has a method persisted? to determine if an object has persisted.
If you're using erb, do
<%= f.submit (#list.persisted? ? 'Create' : 'Update) %>
If you're using haml, use
= f.submit (#list.persisted? ? 'Create' : 'Update')
For more, see http://apidock.com/rails/ActiveRecord/Persistence/persisted%3F

Resources