Implementing Decorators with Rails app - ruby-on-rails

I'm trying to do something very simple with Decorators. I've never personally setup a decorator and I'm trying to spend a bit of time learning about it. Basically I'm trying to take an attribute of a table and build some view logic around it. Here is my code:
Pages Controller:
def dashboard
#assignments = current_account.assignments.all.decorate
#invitation = Invitation.new
end
dashboard decorator:
class AssignmentDecorator < Draper::Decorator
def status
if finished
"Finished"
else
"Waiting"
end
end
end
View table:
<tr class="assignment-rows">
<td><%= link_to assignment.name, account_assignment_path(assignment) %></td>
<td><%= assignment.assigned_workers %></td>
<td><%= assignment.status %></td>
</tr>
As you can see I'm trying to call my assignment method in the td there. but I'm getting this error when I try to render the dashboard:

Use:
#dashboard = Dashboard.find(dasboard_id).decorate
EDIT:
It looks like you want an assignment decorator instead of a dashboard decorator.
Generate a new one with Draper, and then:
#assignments = current_account.assignments.all.decorate

Related

Saving to database in Ruby on Rails without printing?

I'm new to Ruby on Rails, and am working on a finance app to aggregate all of my spending. I am collecting all of my data through a form, then showing it all in a different file called show.html.erb. I want to add up all of my spending in show.html.erb, and have so far been able to do it like so:
<strong>Total:</strong>
<td><%= #article.total = (#article.checking_accounts + #article.savings_accounts - #article.debt) %></td>
<td><%= #article.save %></td>
However, because the .save command returns a boolean, I am getting my result on my webpage followed by "true" i.e. "544 true" rather than just 544. How do I save to the database without printing to my webpage?
As already said, you should try to have the least amount of logic in your views.
Normally saving data is done by the Create action in a Controller. So, you should have something like this in your controller:
# articles_controller.rb
...
def create
#article = Article.find(params[:id])
#article.total = #article.checking_accounts + #article.savings_accounts - #article.debt
#article.save
end
def show
#article = Article.find(params[:id])
end
...
And this in your view:
# show.html.erb
...
<strong>Total:</strong>
<td><%= #article.total %></td>
...
You should not put #article.save inside your view, it should be in your controller, or a callback in your model, but since you just starting, I think, for a quick temporary solution, you can do this:
<% #article.total = (#article.checking_accounts + #article.savings_accounts - #article.debt) %>
<% #article.save %>
<strong>Total:</strong>
<td><%= #article.total %></td>
You can use <% ...%> if you want the process to run but do not want it to print. You can use <%= ... %> if you want to print the value.

Conflicting View Logic

I have a show page where I need to both show the student's units and create a unit for them. However an error is being incurred when trying to do both.
In my controller
def show
#student = Student.find(params[:id])
#unit = #student.units.build
#units = #student.units
end
In my view
<%= simple_form_for #unit, url: student_units_path(#student) %>
# form...
<% end %>
<% #units.each do |unit| %>
<tr>
<td><%= unit.course %></td>
<td><%= unit.mailing_date.strftime('%m/%d/%y') %></td>
</tr>
<% end %>
The unit.course call works and any call that is only the first child of unit, however when I call a second method on unit I get this error:
undefined method `strftime' for nil:NilClass
despite knowing that the unit exists, hence the first call working
It seems your issue is that unit.mailing_date is nil, for newly-built records.
One solution would be to define a default value for mailing_date, either at the database level or in your application. For example, you could do something like:
class Unit < ActiveRecord::Base
# ....
after_initialize :set_default_mailing_date
private
def set_default_mailing_date
self.mailing_date ||= Date.today
end
end
Or alternatively, you could leave the mailing_date as nil and handle this gracefully in the view:
<td><%= unit.mailing_date.try!(:strftime, '%m/%d/%y') %></td>
If you are using ruby version 2.3+, then I would advise using the built-in safe navigation operator, rather than ActiveSupport's try! method:
<td><%= unit.mailing_date&.strftime('%m/%d/%y') %></td>
Finally, if you went with the above choice to leave the mailing_date as nil, then perhaps you'd like to display some default value in its place - for example:
<td><%= unit.mailing_date&.strftime('%m/%d/%y') || 'Not set' %></td>
As an alternative, I assume you don't want the new unit bound to the form being rendered which is what is causing the error.
You could do
#units = #student.units.reject(&:new_record?)
To remove the newly built unit from the collection

How to call a controller method in an associated view file?

I am trying to create a method in a controller file, and then call that method in the index.html.erb view file.
Here are both my index action and my custom method in the controller file:
def index
#mustdos = current_user.mustdos
end
def calculates_mustdos_days_left
((mustdo.created_at + 7.days - Time.now) / ( 60 * 60 * 24)).round
end
helper_method :calculates_mustdos_days_left
And here is the relevant code from my associated my index.html.erb file:
<% #mustdos.each do |mustdo| %>
<tr id="todo-<%= "#{mustdo.id}" %>">
<td><%= calculates_mustdos_days_left %></td>
</tr>
<% end %>
I am getting this error:
NameError in Mustdos#index
And it is referencing this line from my index.html.erb view file
<td><%= calculates_mustdos_days_left %></td>
How can I resolve this? Thanks.
In general, I try to leave my helper methods for when I need them to generate content/output for a view. When I want to calculate and return data regarding a particular Model instance, I either add that code to a Service or the model itself.
app/models/must_do.rb
def days_left
((self.created_at + 7.days - Time.now) / ( 60 * 60 * 24)).round
end
Then, in my view, it's easy to access this off the model's instance:
<% #mustdos.each do |mustdo| %>
<tr id="todo-<%= "#{mustdo.id}" %>">
<td><%= mustdo.days_left %></td>
</tr>
<% end %>
For me, this is a cleaner implementation of the desired behavior. Wanted to offer it as an alternative/additional approach to #IS04's answer.
you could try:
helper_method def calculates_mustdos_days_left(mustdo)
((mustdo.created_at + 7.days - Time.now) / ( 60 * 60 * 24)).round
end
and then in your view file:
<% #mustdos.each do |mustdo| %>
<tr id="todo-<%= "#{mustdo.id}" %>">
<td><%= calculates_mustdos_days_left(mustdo) %></td>
</tr>
<% end %>
but instead controller methods you should use helper methods, also if your method is more general (related to model) and doesn't depend from view, you could define it in your model as #craig.kaminsky written
You can't do it. You can't call methods outside of the controller action you are in in your view. If you have a piece of logic like that you should really try to get it into a model. In this case I would put this method in the mustdo model.
But in those cases where putting the logic into a model does not make sense you can use helper namespaces. It is sort of a miscellaneous drawer for methods that don't quite fit anywhere, like display logic. Helpers go in the app/helpers/ directory. By default there is a helper namespace file in there called application_helper.rb. Any method you put in there will be available in all your controllers and views.

How to display all instances of a model in Rails?

In my web application the user can select certain instances of an entity. For instance on the class BubbleGum, now the user can select certain instances of BubbleGum by adressing their identifier:
gums/details?show=3532667
Now, in addition I also want to make it possible to display all BubbleGums. For this I have introduced the convention of using * to identify all
gums/details?show=*
This works nice so far, but often I have to add a bit code to process the * selection. Is there a nice way to represent an all-instances object in Ruby and/or Rails?
I have thought of using simply a dedicated symbol, constants, or an actual object of the class BubbleGum that represents all the other bubble gums.
To display all the entities in a rails application generally we use a index page.
bubble_gums_controller.rb
def index
#bubble_gums = BubbleGum.all
end
views/bubble_gums/index.html.erb
<% #bubble_gums.each do |bubble_gum| %>
<tr>
<td><%= bubble_gum.name %></td>
<td><%= bubble_gum.price %></td>
</tr>
<% end %>
Refer this for further details.
http://guides.rubyonrails.org/getting_started.html#listing-all-posts
I think you want to use the query string param show.
So, you can try in your gums controller:
def details
if params[:show] == "*"
#bubble_gums = BubbleGum.all
# ...
elsif params[:show]
#bubble_gum = BubbleGum.find(params[:show])
# ...
else
render :status => 404
end
end

Create a class to populate page in ruby 1.8.7

I'm trying to make a class to populate a deals tab on my website.
Part 1. Take an items close date (CatalogItem.close_date) and use all items within 12 hours of closing. Part 2. Calculate the deal percentage by using the current price (CatalogItem.current_price) and estimated value (Item.estimated_price) <-- You'll notice they're in different tables but they're identified by an identical item_id.
I'm green in RoR, so I'm having trouble connecting this in a class, but I can make it work individually in the console:
hour_diff = (CatalogItem.last.close_date - Time.now) / 1.hour
deal_percentage = (CatalogItem.last.current_price.to_f / Item.last.estimated_price)*100
As you can see I'm using my .last piece of data, but I want to create an array that runs through all my items, that's where my knowledge goes dry, any help would be much apreciated
I'm assuming you are using a belongs_to, but I think what you want to do is use
an instance method. This would be your model, app/models/catalog_item.rb
class CatalogItem < ActiveRecord::Base
belongs_to :item
def hours_remaining
(close_date - Time.now) / 1.hour
end
def deal_percentage
(current_price.to_f / item.estimated_price)*100
end
end
Then, you could access them in a view something like this:
<table>
<% CatalogItem.all.each do |ci| %>
<tr>
<td><%= ci.hours_remaining %></td>
<td><%= ci.deal_percentage %></td>
</tr>
<% end %>
</table>

Resources