how to check for non-nil value of associated attribute - is there a more succinct way? - ruby

I have items and they have prices in a has_one relationship. In the price object, there is a price value (unfortunately true). I'd like to be able to test for non-nil values of item.price.price. In the view, there is an add_to_order helper method that should show only if there is a price.price. I test using for this condition with:
<% if item.price && !item.price.price.nil? %>
<%=add_to_order item %>
<% end %>
but it seems pretty ugly. Is there a more succinct / 'better' way of testing for this?
thx in advance

I would try to avoid logic in your views and simply have your add_to_order method handle the item validation.
def add_to_order(item)
return unless price = item.price.try(:price)
# ... your implementation
# the items price is in the price variable for you
end
Object#try
Your view would just become:
<%=add_to_order item %>
since all your logic would be in the add_to_order helper method.

Rails provides a syntax sugar for this with the try method:
<% unless item.price.try(price).nil? %>
<%= add_to_order item %>
<% end %>

You can use try. It will work safely even if item.price is nil
<% unless item.price.try(:price) %>
<%=add_to_order item %>
<% end %>

Related

How to add a class to a number_field bound to model object

No idea why this isn't working, have read through a lot of doc examples, most of those focus on text_field, maybe number_field is weird? I know that number_field doesn't accept a length option...
<%= form_for #person do |p| %>
<%= p.number_field :zipcode, class: "short-number-field" %>
...
<% end %>
The html never renders with the class, how do I do this?
Note, this is not a number_field_tag, so the number of arguments is 2.
Thanks!

Conditional HTML attribute

In ActionView I need to display an attribute based on a condition.
<%= f.text_field :regmax_remote, {
:class => 'span2',
:style => "display:#{#event.regmax_remote.present? ? "block" : "none"};"
}
%>
Is there a prettier way to go about this?
The above code is fine, If you are going to use it only once in the,
But If this will be used in many places then u may need helper
def event_display_style event
event.regmax_remote.present? ? "block" : "none"
end
if you have multiple attributes based on several conditions then u can use the helper to return the attributes in hash format and use it like this.
<%= f.text_field :regmax_remote, event_display_style(#event) %>
if u want a variable hash with default hash then u can do something like this as well
<%= f.text_field :regmax_remote, {class: "span2"}.merge(event_display_style(#event)) %>
There are some other ways to make this code look better. U may also like the draper gem. which gives an object oriented control over displaying at the same time can acce view helpers.
https://github.com/drapergem/draper
You can try like the following,
<% if (#event.regmax_remote.present?) %>
<%= f.text_field :regmax_remote, class: "span2" %>
<% end %>
Do not copy the same, just edit as per your code and use this as the example.

Sinatra query collection

I'm new to Sinatra and I'm trying to figure out how querying a collection in templates work. In this particular example I'm trying to find out if in a specific collection (c in this example) of objects if there is an object with a certain value.
<% if c.votes #then filter by an id for example through all of the objects... %>
yes, it exists
<% else %>
nope, doesn't exist
<% end %>
Also, I'm used to django's filters, is there a comparable documentation online that outlines the various query functions for Sinatra?
Is it just a standard collection? You could use any?, which returns true if the provided block ever finds a match. You would then test each object for the value you are looking for in that block.
<% if c.votes.any? { |a| a.id == whatever } %>
...
<% else %>
...
<% end %>
It really depends on what "votes" is.
In rails you would use <% if c.votes.present? %> which is helpful because otherwise if c.votes is an empty array the condition would evaluate to true.
In Sinatra you don't have .present?, but you have a couple options: <% unless c.vote.empty? %> or <% if !c.votes.empty %>. I don't like the readability of either option, so I would recreate add the present? method to Array:
class Array
def present?
!empty?
end
end
Where you add this depends on how you have your Sinatra app setup. One option would ti added it directly to your main app file.

Sorting and manipulating a hash in Ruby

In my rails 3.1 project I have a Book model that has a ID, NAME, and BOOK_ORDER. I am using the ranked-model gem, which for its sorting process creates large numbers in the sorting(:book_order) column. Im looking for some help to create a method to sort all of the Books by the :book_order column, then simplify the :book_order numbers.
So, I have this:
controller
#books = Books.all
view
<% #books.each do |book| %>
<%= book.book_order %>
<% end %>
# book1.book_order => 1231654
# book2.book_order => 9255654
# book3.book_order => 1654
But want this:
view
<% #books.each do |book| %>
<%= book.clean_book_order %>
<% end %>
# book1.clean_book_order => 2
# book2.clean_book_order => 3
# book3.clean_book_order => 1
Additionally, i don’t want to change the database entry, just use its current values to make simpler ones.
Thanks!
UPDATE:
Thanks to nash’s response I was able to find a solution:
In my Book Model I added the clean_book_order method:
class Book < ActiveRecord::Base
include RankedModel
ranks :book_order
def clean_book_order
self.class.where("book_order < ?", book_order).count + 1
end
end
<% #books.each do |book| %>
<%= book.book_order_position %>
<% end %>
EDIT:
Oh, I see. https://github.com/harvesthq/ranked-model/issues/10

hash enumeration and using outside arguments

I have a form builder and the normal |f| variable. In the middle I'd like to iterate over some hash and get a list of keys by which to build the form. How can I incorporate "f" as an argument to the enumerator.
<%= form_for ..... do |f| %>
<% available_types.each do |k,v| %>
<%= f.text_filed :selection, :value => v %>
<% end %>
<% end %>
As you can see in the code above, "f" is outside of the scope. Ideas?
f should still be in the scope. You misspelled text_field though.

Resources