I have a hash of values that I am trying to loop through to display the values in my view.
The hash is set up as:
{:position=>#<Position id: 2, user_id: 1, title: "Something", city: "Denver", state: "CO",
created_at: "2012-07-06 02:55:42", updated_at: "2012-07-06 02:55:42">, :experience=>[#
<Experience id: 4, user_id: 1, position_id: 2, description: "Did some stuff", created_at:
"2012-07-02 06:24:33", updated_at: "2012-07-02 06:24:33">, #<Experience id: 6, user_id: 1,
position_id: 2, description: "Did other stuff", created_at: "2012-07-02 06:24:33",
updated_at: "2012-07-02 06:24:33">]}
It is created by taking ActiveRecord results and inserting them into a hash (if you want more details, I am happy to add them).
In my view, I attempt to loop through the hash:
<% for i in 0..#positions.length %>
<%= #positions[i][:position][:title] %>
<%= #positions[i][:position][:city] %>
<% end %>
When I open it in the browser, I get an error undefined method '[]' for nil:NilClass. If I only use #positions[i], it will dump out the raw hash (first one, then second, and so on). It's when I add [:position], it doesn't work. I can access the values in the console using #positions[0][:position][:title]. When I tried writing the loop in console, I got the same error.
I know that i is counting because I can have it display the value in the browser and it is working correctly.
I have tried using #positions.each do |job| but ran into the same error. I tried adding another indices in other places: #positions[i][:position][0].
Basically, I have two models: Position and Experience. Experience is a child to Position. I want to get Experience for a given Position but only certain experience like ones that occur within a certain time frame. There is most likely a better approach to this and I just don't know it so I'm open to suggestions.
Thanks.
It seems you have an object of Postion class assigned to the key :position. So you access title and city through accessor methods and not with [].
<% #positions.each do |job| %>
<%= job[:position].title %>
<%= job[:position].city %>
<% end %>
Related
I'm wanting to output some data and I'm not sure if it is possible or not without changing my data file. Basically I have a YAML file with the following structure
items:
- category: red
name: super fun times
note: likes fun
- category: red
name: sunshine
note: wear sunglasses
- category: blue
name: crazy face
note: avoid.
What I'm doing is looping through like so
<% data.options.items.each do |q| %>
<h2><%= q.category %></h2>
<p><%= q.name %></p>
<% end %>
I'd like to be able to do is group items by category when it outputs so it would be something like the following.
<h2>red</h2>
<p>super fun times</p>
<p>sunshine</p>
<h2>blue</h2>
<p>crazy face</p>
I pretty much just want to output the category once, list out the items under that category and then when a new category comes up output that one and any relevant data, without having to repeat chunks of code.
An approach you can take is using group_to to cluster the items by their group, resulting in sets of arrays for each category:
<% data.options.items.group_by(&:category).each do |group| %>
<h2><%= group.first %></h2>
<% group.last.each do |item| %>
<p><%= item.name %></p>
<% end %>
<% end %>
In this scenario, running group_by on the collection of items provides an object with the following format:
{"red"=>[{"category"=>"red", "name"=>"super fun times", "note"=>"likes fun"},
{"category"=>"red", "name"=>"sunshine", "note"=>"wear sunglasses"}],
"blue"=>[{"category"=>"blue", "name"=>"crazy face", "note"=>"avoid."}]}
This allows you to then iterate through the object, making it easier to keep the groups separate in the markup.
Hope it helps!
Given the following two classes Customer and Order, I have a problem which I have narrowed down to the execution times of the callbacks I am using.
The reason for the use of callbacks is that I need to store the aggregated diff of each customer without having to iterate through all of his/her orders each time. So I realized that it might be a good approach to use callbacks to first update the diff on each individual order before each save, and second, update the aggregated diff on the customer model after each order is saved.
The symptoms I get are weird seemingly random errors where it tells me that the diff between two orders which both totals $238 is $15. When I limited the debugger to the affected customers I realized that it was simply skipping the orders.each loop below (but only in some cases) because there were no orders associated to the customer.
Since all Customers have at least one order and the order is actually created before the customer in this system, that can't be true.
Is there some way I can enforce that the after_save callback is indeed not called until ActiveRecord has finished both saving the Order object and updating the relation to the Customer model?
As you can see I also tried to use a timer to see if I could get to work by sleeping the thread for a short while before continuing, but that did not work.
class Customer < ActiveRecord::Base
...
has_many :orders
before_save :calculate_shipping
def update_total_diff
sum = 0
orders.each do |o|
if o.diff.present?
sum += o.diff
end
end
# HERE IS THE PROBLEM: When inspecting the orders collection in the debuggger it is empty.
# Make sure shipping is updated
calculate_shipping
# Since we are calculating the diff shipping must be subtracted
sum -= shipping
self.total_diff = sum
self.save
end
...
private
def calculate_shipping
...returns either 15 or 0
end
end
And the Order model:
class Order < ActiveRecord::Base
...
belongs_to :customer
before_save :update_diff
after_save :update_customer
private
def update_diff
#Updates a local value
......
end
def update_customer
#Here we trigger a function on the customer model in order to tell it that it needs to re-calculate
sleep(1/10) #Tried this to test - no luck
if self.customer_id.present? && diff.present?
self.customer.update_total_diff
end
end
end
Edit:
Have a look at this:
From: /vagrant/app/models/order.rb # line 23 Order#update_customer:
21: def update_customer
22: if self.customer_id.present?
=> 23: binding.pry
24: end
25: if self.customer_id.present? && diff.present?
26: self.customer.update_total_diff
27: end
28: end
...
[4] pry(#<Order>)> michael = self.customer
=> #<Customer id: 2, name: "Michael xxx", mail: "xxx#gmail.com", shipping_address_id: 2, created_at: "2014-07-17 11:00:12", updated_at: "2014-07-17 11:00:12", shipping: #<BigDecimal:7fada4e707d0,'0.0',9(36)>, total_diff: nil>
[5] pry(#<Order>)> michael.orders
=> []
[6] pry(#<Order>)> michael = Customer.find(2)
=> #<Customer id: 2, name: "Michael xxx", mail: "xxx#gmail.com", shipping_address_id: 2, created_at: "2014-07-17 11:00:12", updated_at: "2014-07-17 11:00:12", shipping: #<BigDecimal:7fada5008098,'0.0',9(36)>, total_diff: nil>
[7] pry(#<Order>)> michael.orders
=> [#<Order id: 2, pledge_id: 4808304, amount: #<BigDecimal:7fada50fc120,'0.89E2',9(36)>, customer_id: 2, perk_id: 9, created_at: "2013-11-23 00:00:00", updated_at: "2014-07-17 11:00:12", diff: #<BigDecimal:7fada5108240,'0.0',9(36)>>]
[8] pry(#<Order>)>
I tried stopping my debugger right before the Order tells Customer to re-calculate. I tried assigning the same customer twice to the variable "michael". If I assign the variable simply with:
michael = self.customer
The object won't know about any of its associated orders. If I assign it thorugh activerecord like so:
michael = Customer.find(2)
It will work. Why is that?
For now I managed to fix it by doing this, but I'd still like to know if anyone can explain the situation for me?
me = Customer.find(id)
me.orders.each do |o|
if o.diff.present?
sum += o.diff
end
end
I am using rails 4 and making an application in which Question_sets has many Questions and Questions has many answers. Now what i want is to update one attribute of question model and one attribute of answer model through questions sets.
#question_set.questions.inspect
It gives the output
OUTPUT:
ActiveRecord::Associations::CollectionProxy
[Question id: nil, title: "werewr", question_type: "Slider", description: "ewrewrew", is_shown_in_report: false, question_set_id: nil, user_id: nil, created_at: nil, updated_at: nil]
But when i am accessing any of the attribute or trying to update it, it will give an error that is undefined "attribute_name".
can any tell how to access the attributes of the this collectionproxy object.
questions is returning a collection (like an Array) of Question objects. So you need to itterate over the collection:
#question_set.questions.each do |question|
question.title
end
I have a constant called PAYMENT_METHODS in venue.rb.
PAYMENT_METHODS = ['Visa', 'MasterCard', 'American Express', 'Diners', 'JCB', 'Bankomat', 'sodexo', 'MA-Gutscheine']
You can check/uncheck the payment types in a form (payment_options is an integer):
<%= hidden_field_tag "venue[payment_options][]", nil %>
<% Venue::PAYMENT_METHODS.each do |category| %>
<%= check_box_tag "venue[payment_options][]", category %>
<%= label_tag category %>
<% end %>
Now I want to save the selection, but the value of each check box is the name of the payment option. I think I have to somehow add a key an store only the keys.
How do I set keys and save the collection to the database?
Thanks in advance
Make the constant a hash or an array, e.g.
PAYMENT_METHODS = {'Visa' => 1, 'MasterCard' => 2, 'American Express' => 3, 'Diners' => 4, 'JCB' => 5, 'Bankomat' => 6, 'sodexo' => 7, 'MA-Gutscheine' => 8 }
These will now be in a format that you can pass to options_for_select http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-options_for_select.
If you (really) want checkboxes, an array is fine, just loop over using PAYMENT_MTHODS.each_index do |index| to get an iterator that's the value, and then use PAYMENT_METHODS[index].
I have always found it odd that the hash key is the part displayed in the list, but I guess it makes sense that the value is what is associated with the option's value :-).
Save the string value itself nothing wrong with that.
Its better to create a model like PaymentType and just keep id,name and in view render all payment types.This way you can better manipulate all available payment options in future from an admin panel (if needed) rather than going to a code level and changing at the constant.
You can use an element's index as a key. Use Array#index to your advantage.
PAYMENT_METHODS.index("Visa") #=> 0
PAYMENT_METHODS[0] #=> "Visa"
PAYMENT_METHODS.index("Diners") #=> 3
PAYMENT_METHODS[3] #=> "Diners"
A word of caution: This will break if you reorder PAYMENT_METHODS. You are keying an element to it's relative position in the array. Change the array and you change the keys. Avoid trouble by keeping your constants constant.
In regards to
I have always found it odd that the hash key is the part displayed in the list, but I guess it makes sense that the value is what is associated with the option's value :-).
you can get that done by (it was bugging me a bit as well)
<% Post::TECH_CATEGORY.each do |category| %>
<%= label_tag 'name', category[0] %>
<%= check_box_tag 'tech_cat', category[1] %>
<% end %>
It makes sense now that I can see it on the screen. Each object has two values, so...
category[0]
will always be the key you supplied for that specific object you are currently enumerating over
category[1]
will be the value of that same object. Looks way better on the screen.
which looks like in your example above
<label for="name"> Visa </label>
<input id="tech_cat" name="tech_cat" type="checkbox" value="1" />
Cheers,
I'm trying to get this to work in one of my views:
<%= text_field_tag :sources, "Test", params[:sources] %>
but I get undefined method 'stringify_keys' for nil:NilClass. The code
<%= text_field_tag :sources, "Test" %>
works fine and pre-fills the box with "Test" (but doesn't pass params properly), while the the code
<%= text_field_tag :sources, params[:sources] %>
passes params properly but doesn't have the text "Test" where I need it.
Does anyone know the syntax or a workaround?
The syntax you're looking for is documented:
text_area_tag(name, content = nil, options = {})
The problem with your code is that given three arguments text_field_tag expects the third to be a Hash, but params[:sources] is giving nil. Are you expecting it to hold a different value? Where is params set, and what does it contain?
If you know that params[:sources] will sometimes contain a Hash and other times be nil (i.e. not set) then you could use e.g.:
<%= text_field_tag :sources, "Test", params[:sources] || {} %>
params[:sources] || {} will evaluate to an empty Hash ({}) whenever params[:sources] is falsy (e.g. nil), which will avoid the error.