Rails - Dynamic Nested Forms for Only One Element - ruby-on-rails

I've to modals teams and players, and as usual team has many players.
In teams' show page, I'm showing the players and so on. (I've followed railscasts.com/episodes/196-nested-model-form-part-1 tutorial.)
My problem is, when I click on the player's name in team show page, I would like to show team's edit form but with only clicked player's data in it.
In current case, I have huge form which has all players' information.
That would be great if you can help me.
Thanks.

You could put a hidden_field in your team form that passes the player_id to the controller as a parameter when submitted.
In the controller you could then perform a search only for the params[:player_id] and change your view s you display that.
In your form:
<%= form_for .... do |f| %>
<%= f.hidden_field 'player_id', value: player.id %>
...
<% end %>
In your controller:
if(params[:player_id])
#information = Information.find_by_user_id(params[:player_id].to_i)
end
And, finally, in your view, you can display the #information variable as you wish.
If you dont want to submit to your controller write a javascript program:
$(document).ready( function () {
$(".team_form").live("click", function() {
$(this).attr("player_id").val //holds the player_id
//load the other form using the player_id
}
}

Related

How to make the collection in a select input dependent on the value of another select input

I'm not even sure where to start here, so if anyone can even just point me in a potential direction that would be helpful.
I have a form in my Rails app with two select inputs.
Here's the independent select
<%= collection_select(:pass, :route_id, Route.all, :id, :name) %>
Here's the dependent select
<%= collection_select(:pass, :afternoon_trip, Trip.all, :id, :departure) %>
Right now each Route (from the independent select) has a number of trips associated with it. The Trip (dependent) select shows all trips as options.
I want to only show in the Trip select only the trips that belong to the selected route. Any thoughts on how to do this?
I also want to change the trip options when someone changes their route selection, but this is a secondary issue.
Thank you!
I think you'd want to tackle this one with some ajax. Get the selected option's id, send that to your controller, and render a new menu based on the data the controller sends back. Pseudo code and coffeescript might look like:
# javascript
selectMenu = $('menu selectors')
selectMenu.mouseUp ->
selectedId = // get menu's selected id
$.ajax "path/to/populate_dependant?selected_id=" + selectedId
# controller
def populate_dependant
id = params[:selected_id]
#collection = Model.where(attribute: id)
respond_to do |format|
format.js {}
end
end
# populate_dependant.js.erb
// write javascript to append the following to your form:
<%= f.label :model %>
<%= f.collection_select :model_id, #collection, :id, :attribute_name, :prompt => "Select something" %>
The mouseUp event does not work in steel's answer and it is not clear how to reload the page. The following worked for me. Assume the page where the menu is located is the show action of the trips controller.
The coffee script is
selectMenu = $('#route_select')
selectMenu.change ->
selectedID = $('#route_select :selected').text()
$.ajax "/trips/populate_dependant?selected_id=" + selectedId
Change the populate_dependant to
def populate_dependant
id = params[:selected_id]
session[:collection] = Model.where(attribute: id)
respond_to :js
render :populate_dependant
end
This stores the collection in the session. Then create a new coffee script page in the views for the controller.
#app/views/trips/populate_dependent.coffee.erb
window.location.reload();
This reloads the original page. Then add the following to the show action
def show
...
#collection = session[:collection]
...
end
This works very quickly if using turbolinks.

Using Thumbs_up to display users who voted on a post

I'm using Thumbs_Up gem to let users vote on a post(called Topic). I've done the voting part but now I want to display the users who voted on that particular post. I'm very new to Ruby On Rails, and I'm stuck at the view part.
Here's my controller: app/controllers/topics_controller.rb
def vote_who
#topic = Topic.find(params[:id])
#vote_list=#topic.voters_who_voted_for
end
In my index.html.erb, I want to display the names of there users who voted on that post. This should be right next to the vote button. Kind of like this,
But how do I send back information from the controller?
Or is this approach completely wrong?
IMHO, it's more preferable to show all voters in the 'show' view of the each particular Topic (imagine you have 100 voters for one topic, what this table in index view will look like?).
This way you don't need any distinct action (due to Rails conventions 1 action == 1 view (in general)). Just put in your show action:
def show
#topic = Topic.find(params [:id])
#vote_list = #topic.voters_who_voted_for
end
Then in your view (show.html.erb) you need to do something like this:
<% #vote_list.each do |voter| %>
<%= voter.email %> #or login, or name, or any user's attribute you want to display in your list
<% end %>
Or even try to simplify this: leave show action in your TopicsController as it is (don't create any #vote_list variable, only find right Topic), and call voters_who_voted_for method inside your show view, e.g.:
<%= #topic.title %>
<%= #topic.body %>
<%= #topic.voters_who_voted_for %>

Rails - Submit multiple forms on same page

Model:
Users have expenses. Expense has a status.
View:
As users add their expenses, they are shown in a list. Each expense row has a form button on the end, which is used to submit the expense (changing the status of the expense). This allows users to add expenses they have not completely filled out, and submit them when they are ready. There is no parent form on this page, just the form buttons which submit the expense to a method which changes the status, and then reloads the page.
Currently it works great, but users have asked to be able to "submit all" the expenses that are showing on the view with a single button.
Question:
What is the proper way to handle this in rails? Should I find a way to gather the array of expense id's and then submit a separate form? Is there a way to ask for a set of records present in a view with a certain status?
Thanks!
Another option, if I'm thinking about this right (big if), would be to wrap your page in a User form. Then you could have something like...
<%= form_for(#user) do |f| %>
<% #user.expenses.each do |expense| %>
<% f.fields_for expense do |e| %>
<!-- expense form -->
<% end %>
<% end >
<% end %>
This is something you could submit as a whole. I'm having trouble picturing what a single expense addition might look like, but hopefully this gets you a little further down the road.
Edit: in addition to having this User form on the page, you could have an "extra" Expense form to create an expense. When you submit a new expense, that expense appears in the list under the user form, where it can be edited or submitted, either as part of a group or individually (as part of a "group" of 1).
custom controller action:
def update_all_expense_statuses
expenses = current_user.expenses
ExpenseUpdater.new(expenses).update_expense
redirect_to :back
end
expense updater class:
class ExpenseUpdater
def initialize(expenses)
#expenses = expenses
end
def update_expense
#expenses.each do |expense|
expense.update_attributes(status: 'paid')
expense.save
end
end
end
This is just an example of one way to update all the user's expenses with a custom controller action. Just call the controller method from a link_to:
<%= link_to "Update all expenses", update_all_expense_statuses_path %>
Remember to add it to your routes. Hope this helps.
The first thing you should do is change the forms to submit remotely, ie make an ajax request. Then you're not reloading the whole page. Check out Rails' various "remote" form helpers, eg "remote_form_for".
Then, write a javascript function to submit all the forms for inputs that have changed since the page loaded. You'd probably want to add a "changed" (or similar) class to the parent form in an onchange event in each input, to facilitate this. I think this is the best way to handle the "status" thing you're asking about. Make a "Submit all" button which calls this function.
Use a form/service object http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/ to encapsulate expense report

How to calculate a default value for a form text field in Ruby on Rails?

I have a form for payments like this:
<%= f.label :invoice_id %>
<%= f.select(:invoice_id, current_user.outstanding_invoices_collection) %>
<%= f.label :amount %>
<%= f.text_field :amount %>
I wonder if there's a way to populate the value of the amount text field somehow, e.g. with the open balance of the associated invoice?
In my Invoice model have this function:
def balance
payments.map(&:amount).sum - total
end
How can this be done?
Im assuming you want to populate the text box based on the selection of a invoice from dropdown. In that case
The idea is
You need to make a ajax call onchange of the invoice dropdown.
That ajax response should update the value of the text box.
And with rails-3 i think its recommended to do this in unrobustive way. Here is a link you can follow. Start playing with it meanwhile I will try to make something functional. Hope to get a good result again.
Are you looking for how to populate the value only?
Update:
Here is the ajax part
#Application.js or any sutable js file
$(function($) {
$("#your_drop_down_id").change(function() {
#Your the url to your controller action here
$.ajax({url: '/get_amount',
data: 'invoice_id=' + this.value,
dataType: 'script'})
});
});
#in get_amount Action
invoice = Invoice.find(params[:invoice_id]) #Other appropriate logic to get the invoice
#amount = invoice.balance
#get_amount.js.erb
$('#your_text_box_id').val('<%= #amount %>');
#routes.rb
#This part is written following the gist: https://gist.github.com/3889180 by #TinTin
resources :payments do
collection do
get 'get_amount'
end
end
Let me know if any part is confusing to you.
In your controller you can assign any value to any field, and it will be displayed in the view.
def new
#payment = new Payment()
#payment.amount = 100
end
If you want some dynamic value, e.g: based on a combobox selection, then do it in javascript or with AJAX.

Rails Dependent Form - Selecting a Specific Item from a Model

I'm new to Rails so be gentle. I've got a model, 'Event', with the the following information: 'sport', 'home_team', 'away_team', and 'time' in datetime.
Now I want to enable the user to 'follow' a specific event and am trying to find the best way to do so. Ideally, I'd like a form with dependent drop down lists. For example, the user first picks a 'day', then a 'sport', then selects from a relevant list of 'events' of that 'day' and 'sport'. This association is then stored in a rich join table called 'following'.
I've seen tutorials on complex forms that involve multiple models, but what about when everything is from the same model? How do build a form to grab a handful of relevant records. I only have a few distinct values for 'sport', so I wasn't sure it made sense to give it its own model. And can I easily get events on a certain date from a 'datetime' value?
There a lot of ways to go about this, here is one option:
Since you want to see multiple events, you'd probably start off focused on the index action. Start off by creating and index action, but add some hooks to filter it, i.e.
def index
if params[:sport]
#events = Event.where("sport = ?",params[:sport])
else
#events = Event.all()
end
end
Now, if you've defined your routes like this:
resources :events
You'll have a a route /events that will accept a get request and route you to the index action.
But if you want a form where you can select things, a form will by default POST, but you could create a form that GETs to '/events'
i.e. in app/views/events/index.html.erb
<%= form_tag '/events', :method=>:get %>
Then, you want to create your form elements that will send the params.
i.e.
<%= select_tag 'sport', '<option>baseball</option><option>football</option>' %>
Put in a submit button
<%= submit_tag 'See Events'
Then 'end' your form with
<% end %>
Now when you click on the 'See Events' button, you will send a get request to the route '/events', and the 'sport' parameter will show up in the index action, filtering the events.
To keep things simple and all in the index view, after your form you'd list all the events.
<% #events.each do |e| %>
Sport: <%= e.sport %><br/>
Home Team: <%= e.home_team %><br/>
Away Team: <%= e.away_team %><br/>
Time: <%= e.time.strftime('%H %M') %><br/>
<% end %>

Resources