1

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?

Nirupa
  • 787
  • 1
  • 8
  • 20

3 Answers3

1

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.

Community
  • 1
  • 1
bsvin33t
  • 628
  • 9
  • 19
  • // def review_avarage @review = Review.average(:rating) end // and in show view <%= [at]review.review_avarage %> ??? – Filip Maryniak Jun 15 '16 at 23:37
  • usually what I would do is, `def show @review = Review.find(:id) end` app/views/reviews/show.html.erb `Average: <%= @review.average%>` – bsvin33t Jun 16 '16 at 01:49
  • @FilipMaryniak I think what @bsvin33t is suggesting is to add a method on your Review model and then call that method in the view. In your case, in `app/views/reviews` you define: `def average_rating Review.average(:rating) end` and in `app/views/reviews` you you'll have `<%= @review.average_rating %>`. Also if every item has a review (and assuming you've set your associations properly), you'll be able to access its rating via `@item.review.average_rating` in `app/views/items/show.html.erb`. – Ivan A. Jun 16 '16 at 12:55
  • undefined method `average_rating' for nil:NilClass still – Filip Maryniak Jun 16 '16 at 15:00
0

Simply add the following to your show.html.erb :

<%= @model.average_rating %>
Tinus Wagner
  • 927
  • 1
  • 7
  • 15
  • Everything what i do: "undefined method `average_rating' for nil:NilClass" – Filip Maryniak Jun 16 '16 at 10:00
  • have you defined a 'average_rating' method in your model? Also it may have to do with the data type your trying to average (maybe you're dealing with strings?) in your model, define a method .e.g. `def average_rating model.average(:rating).to_f end` – Tinus Wagner Jun 19 '16 at 07:05
  • That error definitely makes me think you're not defining the method correctly in the model. – Tinus Wagner Jun 19 '16 at 07:09
  • I defined in controller `def @rating = Model.average(:rating) end` and into view i defined `<%= @rating %>`. It works, but it shows me a strange number. At first, my item hasn't got any ratings but the controller show i.e. 11.404040 (?). At second, i think, that my method calculate all ratings from all items which belongs to Model, not from one. But it is not solving the first problem, because if I have only one item - it shows me a strange number too. Any ideas? Thanks for all responses. – Filip Maryniak Jun 21 '16 at 07:38
  • So, I'm creating the catalogue, every item in the catalogue has reviews with users rating, i want to calculate average rating from reviews for one item. – Filip Maryniak Jun 21 '16 at 08:24
  • def @rating = Model.average(:rating).to_f Give that a go – Tinus Wagner Jun 22 '16 at 01:41
0

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.