Issue including a second and a third level association - ruby-on-rails

This query is not working, pease help. I'm trying to include a second and a third deep-level of association.
Pedido > has_one(products_pedido) > has_one(product_size)
#pedidos = Pedido.includes(:pedidos_payments, :products_pedidos => { :product_size } , :estado, :brand, :customer ).where(:is_quote => false)
Ps: I know products_pedido is mispelled according to ActiveRecord good practices :).

Without a stacktrace here's what I suggest:
Assuming your has_one method name is products_pedidos, your issue looks like a problem with your hash syntax.
Your syntax creates a hash with key products_pedidos that returns a hash without a value. This is probably where the error is occurring.
#pedidos = Pedido.includes(:products_pedidos => { :product_size })
What you likely want is this which returns a hash with key products_pedidos with value product_size
#pedidos = Pedido.includes({products_pedidos: :product_size })
The Entire query might look like:
#pedidos = Pedido.includes(
:pedidos_payments,
{products_pedidos :product_size},
:estado,
:brand,
:customer
).where(is_quote: false)
Here's a great post explaining a bit more about ActiveRecord nested relationship loading: Rails - Nested includes on Active Records?. I'd also suggest fixing the naming on products_pedido to follow good naming practices.

Related

Controller Chokes on Nested Model's Attributes

I'm using Rails 4 + Ruby 2
Nested models in Rails are a huge pain. There, I said it.
Okay, so I have an entry model with approaches nested inside.
# --- entry.rb ---
has_many :approaches, :dependent => :destroy
accepts_nested_attributes_for :approaches, :reject_if => lambda { |a| a[:approach_type].blank? }, :allow_destroy => true
The approach parameters come over to the controller's create method like this (from the log):
{"utf8"=>"✓",
"entry"=>{
"aircraft_registration"=>"N384HA",
"flight_date"=>"2013-12-10",
"departure"=>"KSAD",
...
"approaches"=>{
"1386633324306"=>{
"approach_type"=>"GLS",
"holding"=>"false",
"quantity"=>"2",
"airport"=>"FFS",
"runway"=>"12L",
"updated_flag"=>"true"
},
"1386633813852"=>{
"approach_type"=>"TACAN",
"holding"=>"false",
"quantity"=>"1",
"airport"=>"DFD",
"runway"=>"12L",
"updated_flag"=>"true"
}
},
}
For testing purposes, I do blanket param allowance:
params.require(:entry).permit!
...and I get this error from Satan himself:
ActiveRecord::AssociationTypeMismatch - Approach(#70114475640640) expected,
got Array(#70114477494560)
It seems that the problem is that the Entry model doesn't like the approaches being an array (which actually looks like a hash with id numbers, but what do I know).
My Question
How should the params look on a nested model when they come over from the view to the controller?
I'm trying to narrow down whether I have mis-formatted data coming from my form, or a problem in my controller.
I'm new to Rails, so please be gentle. :)
To answer your question, a nested model should come through something like this:
params = {
:entry => {
:approaches_attributes => [
{:approach_one_attr => ...},
{:approach_two_attr => ...}
]
}
}
Looks to me like the problem here is with the form in your view not the controller.

Nested attributes in hash representation of a record

I've given up hours of my day trying to accomplish this simple thing in Rails 3.1 with no luck. I've got some models nested 2 levels deep and associated many-to-one with belongs_to/foreign key, like:
TopLevelModel:
MiddleLevelModel:
BottomLevelModel
I am eagerly loading the whole hierarchy in my queries like so:
#model = TopLevelModel.find(1, :include => {:middle_level_children => :bottom_level_children})
The JSON serializer works fine for serializing the nested hierarchy (using the :include option), but this isn't enough for my purposes and I need a (ruby) hash representation of the record's attributes. #model.attributes() would be perfect but it neglects my relations. Is there a way to get a nested hash representation using this method (I read the documentation thoroughly and suspect not, but maybe there's some exotic option I don't know about). To be clear, the representation I am looking for would be:
{
:attribute_1 => 'some attribute', #an attribute of top level model
#...
:middle_level_children: => [{ # type 'MiddleLevelModel'
:attr_1 => 'some attribute of middle level model',
# ...
:bottom_level_children => [{ #type 'BottomLevelModel'
:attr => 'some attribute of bottom level model'
}]
}]
}
This seems like an incredibly simple (and, I would think, common) need, but I've had no luck.
Why can't you iterate through all your child relationships and print all the attributes for each instance of them?
Might be a little hokey but give Hash.from_xml a whirl.
Use the object's to_xml method to serialize with associations and then deserialize with the Hash.from_xml class method.
xml = #model_instance.to_xml(:include=>:middle_level_children)
nested_hash = Hash.from_xml(xml)

ActiveRecord Include, how to use in nested records?

I currently have the following:
#threads = current_user.threads.includes(:user, :thread_members)
I then take threads and do the following:
#threads.each do |thread|
thread_members = thread.thread_members_active(current_user)
#threadList << {
:id => thread.id,
:uuid => thread.uuid,
:user_id => thread.user.id,
:last_activity_at => thread.last_activity_at,
:user_count => thread_members.length,
:user_photos => thread_members.collect { |thread_member|
{
:id => thread_member.user.id,
:photo => thread_member.user.photo(:thumb),
:name => thread_member.user.full_name
}
},
:caption => thread.caption
}
end
The issue here is that every EACH loop, rails is hitting the DB for the same basic records. Rails sees to be caching as I see CACHE in the log but it's mighty messy. Leaves me wishing I could do some type of includes so there wasn't so many db requests.
Any ideas on how this can be optimized? Something around including all the users in one db hit?
Thanks
If you don't want any DB queries in the loop, you have to define everything that's used there in the named associations that are included, so instead of a thread_members_active method you'd define a thread_members_active association which has the same behavior. Note that the association also needs to use includes on user. Can't give you more right now, but maybe that helps a bit.
Edit: Check out the "Eager loading of associations" part of this doc:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Where to store model attribute value translations

I have a model Invoice with attribute payment_status. payment_status has fixed values unpayed|partial_payed|payed that I want to store the translations for in a locale-file.
I thougt it would be good to have it in the model local-file
de:
activerecord:
attributes:
payment_status: Zahlstatus
payment_status_values:
unpayed: offen
partial_payed: teilgezahlt
payed: ausgeglichen
now I can get the translated payment_status-value for the last invoice like this
I18n.t Invoice.last.payment_status , :scope => "activerecord.attributes.invoice.payment_status_values"
=> "offen"
to me it looks like typing sopes a lot, is there maybe a scoped method to get the translation or a better way to do this at all?
We used the easy_enums plugin from marcel. The closest I found was: https://github.com/mschuerig/easy_enums/
Syntax is like this. Then you store only last part of the scope identifier.
has_enum :shipping_mode, :default => :not_set, :fallback => :not_set do
value :not_set
value :address
value :self_collect
define_method(:localize) { I18n.t("models.payment.shipping_mode.#{self.id}") }
end
Does that hit your goal?

searching a model in rails for 2 values?

I wrote this retrieval statement to check if an appointment being saved or created dosent conflict with one thats already saved. but its not working, can someone please point me to where I'm going wrong?
#new_appointment = :appointment #which is the params of appointment being sent back from submit.
#appointments = Appointment.all(:conditions => { :date_of_appointment => #new_appointment.date_of_appointment, :trainer_id => #new_appointment.trainer_id}
)
the error is from the :date_of_appointment => #new_appointment.date_of_appointment this will always be false as:
thank you
At face value, there doesn't appear to be anything wrong with your syntax. My guess is that #new_appointment isn't containing the values you're expecting, and thus the database query is returning different values than you expect.
Try dumping out #new_appointment.inspect or check the logfiles to see what SQL the finder is producing, or use
Appointment.send(:construct_finder_sql, :conditions => {
:date_of_appointment => #new_appointment.date_of_appointment,
:trainer_id => #new_appointment.trainer_id
})
to see the SQL that will be generated (construct_finder_sql is a protected ActiveRecord::Base method).
Update based on your edit
#new_appointment = :appointment should be something like #new_appointment = Appointment.new(params[:appointment]). :appointment is just a symbol, it is not automatically related to your params unless you tell it to.

Resources