Conflicting column names in Ruport report table - ruby-on-rails

When using Ruport to make a CSV file for entities containing the same entities, the generated column names create conflicts, causing Ruport to show only the first occurence of this column(s). To make this abstract explanation more clear and less complicated, an example:
My class Zone inherits from ServerUnitConfig, which has a :belongs_to to a ServerUnit.
So Zone has for example server_unit.su_name as a field.
Zone also has a :belongs_to for Domain, which also inherits from ServerUnitConfig.
I want both to be included in my Ruport and to do this I have the following :include argument for my report_table of Ruport:
{
:server_unit => {:only => 'su_name'},
:domain => {:include => {:server_unit => {:only => 'su_name'}}, :only => {}
}
Reporting this with Ruport in a CSV file, gives a report showing only the server_unit.su_name column of server_unit not the one of Domain. Normally also the server_unit.su_name should be shown, but since Ruport only shows the field name and its parent, both cases show server_unit.su_name and this gives conflicts.
I would suggest to give a custom name to the field in the include, but I don't know how. An other idea, if it would be possible, is to tell Ruport one or the other way it is no problem to have identical column names, but I don't think that is possible. Has anybody an idea to solve this problem? It would help me a lot!
Thanks
Daan

You could use the report_table_by_sql method, which is a bit ugly. Or use the :method option to call a method with a slightly different name, not great either.
There is a :qualify_attribute_names option for each include that was used internally. I've written a patch here: https://gist.github.com/1057518 that will expose it, you can use it like so:
{:server_unit => {:qualify_attribute_names => 'serv', :only => 'su_name'}}
To apply the patch you'd need to "vendor" the acts_as_reportable gem in Rails, which can be a pain. I'll try and put it on the main repo at https://github.com/ruport/acts_as_reportable soon when I'm sure it has no problems.
Hope that helps,
Andrew

Related

Active record querying with store_accesors

I have a database where I need to do a search on specific record that has a certain output. What is making this tricky for me is that these values are found in a 'store_accessor' and therefore they aren't always there.
For instance if I run Team.last.team_configuration, I get this value below, and what I need are only teams that have a specific setting.
<TeamConfiguration:0x00007123456987> {
:id => 8,
:owner_id => 6,
:team_type => "football",
:settings => {
"disable_coach_add" => false,
"delink_players_at_18" => true
},
:type => "TeamConfiguration"
}
My thoughts have been something around these lines, but i keep getting undefined method 'settings' for team_configuration:Symbol
Team.where(:team_configuration.settings['delink_players_at_18'])
Would anyone know what I am doing wrong in this instance? I think because there are two separations from the main source it has been causing me some issues. Thanks in advance!
The problem is way store_accesors works, look what documentation says:
Store gives you a thin wrapper around serialize for the purpose of
storing hashes in a single column. It's like a simple key/value store
baked into your record when you don't care about being able to query
that store outside the context of a single record.
https://api.rubyonrails.org/classes/ActiveRecord/Store.html
So a posible solution could be to search by that column, converting a previously hash of what you want to string.
Team.where(team_configuration: data.to_s)
If you're using a postgres database and the TeamConfiguration#settings column is serialized as jsonb column you can get at this with postgres json operators:
Team.joins(:team_configurations)
.where("team_configurations.settings #> '{\"delink_players_at_18\": true}'")

Rails: OR where condition on association

I have a model called Facility. It has_many :addresses. The Address model has_one :city.
Now I want to run a condition:
to get all facilities that do not have associated address;
if they do have addresses check if they do not have city model associated with that addresses.
I have tried the first condition but I am unable to combine an OR for it.
This gets all facilities that do not have an address model associated to it
Facility.includes(:addresses).where( :addresses => {:facility_id => nil})
Some error tries are:
Facility.includes(:addresses).where( :addresses => ({:facility_id => nil}).or({:city_id => nil}) );
Facility.includes(:addresses).where( :addresses => ({:facility_id => nil}).or(:address => {:city_id => nil}) )
Try the following:
Facility.includes(:addresses)
.where('addresses.facility_id is null or addresses.city_id is null')
.references(:addresses)
You can also find interesting this post, concerning possible implementations of the or condition in the activerecord queries.
Try this
Facility.includes(addresses: :city).where("addresses.facility_id IS NULL OR addresses.city_id IS NULL");
Hope this would be helpful.
First, using includes when you want to do conditions on associations can have negative side effects:
You will eager load data, which, if not needed, means doing more work for nothing
The addresses that are eager loaded are only those matching the condition. So if you thn use addresses, you don't get all of them for that record (only those that matched the condition). This causes weird bug or hard to understand working code.
To avoid this and all other issues, I recommend to use a gem I made specifically for this: activerecord_where_assoc
Your problem can be simplified, I will do so after replying to your request as-is:
You seem to be using Rails 4.2 according to the tags. So you don't yet have access to the #or method yet. So this is how you could do it:
sql_no_address = Facility.assoc_not_exists_sql(:addresses)
sql_no_city = Facility.assoc_exists_sql(:addresses) { where_assoc_not_exists(:city) }
Facility.where("#{sql_no_address} OR #{sql_no_city}")
If you have Rails 5 or more:
Facility.where_assoc_not_exists(:addresses).or(Facility.where_assoc_not_exists([:addresses, :city]))
Now, a simpler solution. Notice that if a facility has no addresses, then it cannot have a city, because it must go through an address to get to a city. Really, your problem is just "I want Facilities that have no cities". This is what passing an array to the methods do, it tries to go from one to the other until the end.
Facility.where_assoc_not_exists([:addresses, :city])
Here are the introduction and examples. Read more details in the documentation.

Why can I access :number_to_currency but not :titleize as helpers in my view?

I think this is the default behaviour. I'm trying to use best_in_place with :display_with => :titleize to format the output.
How can I make sure :titleize is available in this namespace? Applying it to a symbols works, e.g. #name.titleize, but not when passed in as a parameter.
Many thanks!
Chris.
Have you tried with something like this?
:display_with => lambda { |v| ActiveSupport::Inflector.titleize(v).html_safe }
You have to include the complete path because it is not available in the views.
The reason why #name.titleize is working is becuase this method in another one that belong to the String class.
http://apidock.com/rails/ActiveSupport/Inflector/titleize
vs
http://apidock.com/rails/String/titleize

ActiveRecord Includes n+1 issues

I am using the Bullet gem to assist me in finding my n + 1 errors for my ActiveRecord queries. I currently am passing in:
#user = User.includes(:routines => {:lifts => [:exercise, :infos]}).find(current_user.id)
To me this means I am loading the current user, his routines, those routines' lifts, and those lifts' exercise and infos (which are sets).
Is my assumption true?
The Bullet gem is giving me two errors in which it is claiming I need to:
Lift => [:routine] so it says add ".include => [:routine]"
AND
Lift => [:infos] so it says add ".include => [:infos]"
Would somebody be able to explain this to me?
Thank you!
You definitely are on the right path. I highly recommend brushing up on this via http://guides.rubyonrails.org/
Your setup supports pre-loading when you access data like this:
routines = #user.routines
lifts = #user.routines.map(&:lifts)
Can you please describe how you are attempting to access this data? It appears that you may be trying to access routine via:
lift.routine
How are you accessing lift?
You might want to make sure that you use :inverse_of when specifying your associations.
Does Routine have many :lifts?

is there any core function find_by_controller in ruby on rails framework?

My first project as a software engineer is adding features to an existing ruby on rails crm application. I had to add functionality for sending an automated email, for which I just copied and pasted from another place in the program, where this was happening. The trouble is that now I want to modify it. Here's the code that does it?
recipient = session[:registration][:email]
subject = ManagedContent.get_email_subject("checkout", session[:registration][:id])
message = ManagedContent.find_by_controller("checkout").content_text
RegistrationConfirmationMailer.deliver_registration_message(recipient, subject, message, #registration_transaction.registration.id, render_to_string(:template => "registration_invoices/show.haml", :layout => 'none', :locals => {:registration => #registration_transaction.registration, :event => #registration_transaction.registration.event}) )
From what I gather from this that the message to be sent is being crafted in third line by calling find_by_controller() function. However, I can't find that function either in ManagedContent model or controller. I have even done a grep search of the entire workspace for this project, I didn't find any definition. Googling too didn't return anything that I could make sense of. Where can I look for this method definition as I need to make a little modification in the message
Thank you!
find_by_(field) is an ActiveRecord construction letting you find a record based on the value of a field.
See http://guides.rubyonrails.org/active_record_querying.html (especially section 14 on Dynamic Finders).
So you should look for a "controller" column in your managed_content table. Based on the code you copied, there is a row in that table with a value "checkout" for the controller column. In that same row, the value for the "content_text" field is the value you want to change.
PS: Congrats on your first software gig. Enjoy it while still untainted. :)
If your ManagedContent is a ActiveRecord class, doing find_by_controller generates an SQL request on your ManagedContent table to do a restriction on controller columns.
All is in dynamic finder documentation

Resources