displaying a name from an integer in rails 3 - ruby-on-rails

I have a rails 3 app where users select an option from a select input which is stored as an integer. The select input is populated by a :collection with simple_form gem, for a table that I seed. This is working exactly the way that I want.
However, I want to display the name instead of the integer in my views.
Right now I am doing this in the view, which is obviously not a best practice.
<% mfg_num = #product.manufacturer.name %>
<%= "#{ListOfManufacturers.find(mfg_num).name}" %>
So, my question is:
What is the best practice for setting up something so that I don't need to put this logic in my view? Should it be in the controller? Should in be in the model? And how do I do it?

there're couple of solutions to this problem, these are:
use instance variable in your controller and use it in the view, smth like
............
#product.manufacturer
#man_name = ListOfManufacturers.find_by_name(#product)
............
use helper method or method in your model
these're good practice

Related

RUBY ON RAILS 4.2.3 Calculate average

I'm junior RoR programmer.
I know that Ruby language has a calculate method, When I type this in rails console: ModelName.average(:something),it calculates the average value from field :something. It works, but how to add average value to the view?
I have a Items catalogue. Every item has a Review which include rating (integer).
How to display on the view (i.e. show.html.erb) the average value from all rating fields in Review model?
There are multiple ways of doing this. Easiest way is exposing it as a state on the controller, which is the #average, which can then be accessed in the view. As easy as it might be, I don't recommend this approach.
What I do recommend is, adding a method on your model,
model_instance#review_ average and when you are exposing (using the #model_instance) the instance of the model in the #show action of your controller to the view, you can just call #model_instance.review_average
What is the advantage of the second approach? It hides the logic from the view and controller, and pushes it into the model, which in turn makes it easier to write an automated test case.
for implementing average, check: How do I create an average from a Ruby array?
I'm also guessing that you have a has-many relation. It should not be too difficult to do the above.
One thing that you have to also keep an eye for, is n+1 queries, But this becomes an issue only when you have to show the avg in the index page.
Simply add the following to your show.html.erb :
<%= #model.average_rating %>
RESOLVE STEP BY STEP:
first step: Add to your model controller, to def show:
#rating = Model.where(:model_id => params[:id]).average(:attribute).to_i
second step: add to your model view to show.html.erb:
<%= #rating %>
model_id = your model, i.e. Post will be :post_id
:attribute = your attribute, i.e. :rating
It's all.

How can I update multiple rows in a Model using a form in Rails?

I'm trying to make a small app in rails where investors can see their balances. The balances are updated by an admin.
The investors are all in a Model called User - is there any way to set up one form in one view where User.balance can be updated for all Users?
The fields in the view can be populated using a <% User.each do |u| %> loop, I guess, but how can I handle the data in the controller?
Thanks!
It might be convenient to implement this in an index view, by using an Ajax-capable gem such as best_in_place, which would let the values be edited in place without the form being submitted.

Collection_select has always only 1 item, not an array? In ruby on rails

I am implementing in Ruby on Rails and I am trying to work with the collection_select, I'm a newbie. I just want to do, I have a list with groups and a list with roles. These are both models. So, I list my groups, and next to that, I have a dropdown list with the role for the group. each group has 1 role.
I implemented some code already, but the collection_select always only remembers the last item. So I want a list with groups, connected with the desired role. But, now I only have 1 item. This is my view:
<% #groups.each do |group| %>
<li>
<%= collection_select('group', 'role_id', #roles, 'id', 'name') %>
</li>
<% end %>
I don't really know what to do now? Someone who knows what I am doing wrong?
Thanks
So, I assume that you're doing a form? What model does the form belong to?
To help debug this sort of thing, usually it'd be a good idea to check your development.log file to see what parameters the form is passing to the controller. Something like:
Parameters: {"commit"=>"Save", "action"=>"update", "_method"=>"put",
"id"=>"6168", "group"=>{"role_id"=>"2", ...}, "controller"=>"groups"}
Now, usually a Rails controller is expecting a form with the data for a single model. If you're wanting to update multiple models or rows at the same time, you're going to have to get creative.
First thing to do might be to try returning an array of groups. Your form at the moment is not using an array. I doubt that these Rails helpers will help you though. Helpers like these are designed to update one ActiveRecord object at once.
It's possible you may need to rethink the design of your app to better fit the Rails way, or roll your own form and iterate over the array that it passes through. Doing it the Rails way is the recommended option, it just might take some brain bending from your end to figure that part out. If you need help, maybe provide more information on what you're actually trying to achieve.

Rails: How to use fields_for with two objects of the same class in a single form?

I'm trying to use form_for and fields_for in Rails 3 to let me edit two objects (of the same class) on one page, but I'm not having any luck: the second object's HTML input tags come out with the same IDs as the first object's.
The specific situation:
I have a class Card. I'm trying to follow general RESTful patterns for it.
Most Cards stand alone, but a small number of them have a second Card object affiliated with the first one, via the "link" property. (I call these "multipart" Cards.)
I want it to be possible to use the standard Card edit page (views/cards/edit.html.erb and views/cards/_form.html.erb) to switch a Card from standalone mode to multipart mode. I'm using JavaScript to show the second set of edit fields on the form when the user selects multipart mode on the edit page. Therefore, the edit form for every Card needs to
contain the form fields for a second Card, to potentially become the "link"ed Card from the main Card being edited.
The HTML fields for the second Card should be identical to those for the first one. I have a complex pretty HTML layout for my fields and inputs, and I want to keep things DRY and avoid duplicating all that code for the second Card's field.
This turns out to be really problematic. I've tried assorted things like:
<%= form_for(#card) do |outer_form| %>
...
<% [#card, #card2].each_with_index do |card, card_index| %>
<%= fields_for card do |f| %>
This doesn't work because the second object's HTML input tags come out with the same IDs as the first object's. They both come out with HTML <select id="card_rarity" name="card[rarity]">, which seems obviously wrong.
I tried changing the quoted lines to say
<% [#card, #card2].each_with_index do |card, card_index| %>
<%= fields_for (card_index == 0 ? card : card.link) do |f| %>
with the hope that this would then provide HTML names like "card[link][rarity]". (Edit:) But it doesn't: even with fields_for card.link, it still produces form fields with name="card[rarity]". So the page has two inputs with the same name and ID, and discards one of them on submission.
I tried saying
<% [#card, #card2].each_with_index do |card, card_index| %>
<%= fields_for card, :as => (card_index == 0 ? "card" : "card2") do |f| %>
but that didn't work either. The :as parameter seemed to be completely ignored.
Can anyone suggest the approach that I'm missing here? I don't find the official documentation on form_for and fields_for very helpful.
(Edit to add:) In particular, surely there must be a way to edit fields for two different objects of the same class within a single Rails form? fields_for makes it trivial to do this with any number of objects of different classes - but how can it be done for two of the same class?
Many thanks!
You say:
with the hope that this would then provide HTML names like "card[link][rarity]", but the problem there is that Rails calls class_name on the object, and in most cases card.link is Nil. I don't want submission of this form to automatically create a dummy linked card for all cards, which is what I think would happen in this case.
I would pursue this strategy a bit more. In your edit controller action I would add #card.link ||= Card.new to prevent nil access errors; in the update controller action (or in the Card model itself if you want to defer the logic there), make sure that empty "link" cards are discarded.

way of implementing links in rails

I have a project I am doing in rails. I want to implement this sort of links
{user} has {action} on {file} in {project}
each of the words wrapped by curly braces are entities in my system (models). how do I implement saving these changes in the project and how do I get all of the changes from the database and display them to the user?
I am using rails 2.3.8 if it matters
example of the links I need to display (image)
There are some plugins available to keep track of activities in models:
https://github.com/grosser/record_activities
https://github.com/linkingpaths/acts_as_scribe
https://github.com/face/activity_streams
I normally use acts_as_scribe, it's the simplest of them.
I would recommend acts_as_audited. It works very well. It saves all your changes on a model in the form of a hash, so using it becomes as easy as
audit = Audit.first #just for example
In your view
<%= link_to User.find(audit.user_id), user(:id => audit.user_id) %> has
<%= audit.action %>
Of course you will have to customize how your messages will finally appear. And of course its better not to use find methods in your view. I've used it here just for illustration purposes.

Resources