rails query interface joins argument error - ruby-on-rails

I am trying to make use of Active Record Query Interface joins
https://guides.rubyonrails.org/v2.3.11/active_record_querying.html#using-arrayhash-of-named-associations
I have the associations for the two models working correctly, but when I try to run this query...
Package.all :joins => :drugs
I receive the:
ArgumentError: wrong number of arguments (given 1, expected 0)
does anyone know why this might be?

What version of Rails are you running? The documentation is pretty old (v2.3) and a lot has changed since then.
Try using Package.joins(:drugs).all instead.

Related

Sql injection from brakeman for Order by field in rails

Rails version: 5.1.7
Getting Brakeman vulnerability warning for order by field with where clause query in rails
Can, anyone help me to resolve this issue?
Thanks in advance
Query for your reference:
DropdownValue.where(:dropdown_id => PreferenceValue.find(params[:id]).preference.dropdown_id).order("field(id, #{PreferenceValue.find(params[:id]).dropdown_value_ids.join(",")})")
With ActiveRecord sanitize_sql_for_order, i fixed the brakeman sql injection warning
DropdownValue.where(dropdown_id: #preference_value.preference.dropdown_id).order(ActiveRecord::Base.send(:sanitize_sql_for_order, "field(id, #{#preference_value.dropdown_value_ids.join(',')})" ))
I was getting that when using .order("field(id, ...)
Problem
I was trying this inside a model:
scope :order_by_type, lambda {
order_rule = %w[B A C]
order("my_field, #{order_rule}")
}
Then I was getting:
ActiveSupport::DeprecationException: DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "FIELD(my_field, 'B','A','C')"
Solution
I ended up using this neat gem https://github.com/panorama-ed/order_as_specified
It got as simple as
MyModel.order_as_specified(my_field: order_rule)
While not quite a SQL injection vulnerability this whole query is an absolute mess and something that probably should be solved via joining or indirect associations.
You can fix the breakman warning by using a bound parameter instead:
.order("field(id, ?)", PreferenceValue.find(params[:id]).dropdown_value_ids)
It's happening because of this line
"#{PreferenceValue.find(params[:id]).dropdown_value_ids.join(",")}"
do this,
dropdown_ids = PreferenceValue.find(params[:id]).dropdown_value_ids.join(",")
and then in main query
"field(id, #{PreferenceValue.connection.quote(dropdown_ids)})"
connection.quote whitelists the interpolated values.
Give it a try.
Regarding the first answer,
there is no prepared statement in .order() method and this is not a solution.
For my case this one was the working solution:
#skus = skus_scope.preload(...).order(ActiveRecord::Base.send(:sanitize_sql_for_order, "field(id, #{sku_ids.join(',')})"))
You could also go for something cleaner like:
#skus = skus_scope.preload(...).order(sanitize_sql_for_order(["field(id, ?)", sku_ids]))

Rails: Getting column value from query

Seems like it should be able to look at a simple tutorial or find an aswer with a quick google, but I can't...
codes = PartnerCode.find_by_sql "SELECT * from partner_codes where product = 'SPANMEX' and isused = 'false' limit 1"
I want the column named code, I want just the value. Tried everything what that seems logical. Driving me nuts because everything I find shows an example without referencing the actual values returned
So what is the object returned? Array, hash, ActiveRecord? Thanks in advance.
For Rails 4+ (and a bit earlier I think), use pluck:
Partner.where(conditions).pluck :code
> ["code1", "code2", "code3"]
map is inefficient as it will select all columns first and also won't be able to optimise the query.
You need this one
Partner.where( conditions ).map(&:code)
is shorthand for
Partner.where( conditions ).map{|p| p.code}
PS
if you are often run into such case you will like this gem valium by ernie
it gives you pretty way to get values without instantiating activerecord object like
Partner.where( conditions ).value_of :code
UPDATED:
if you need access some attribute and after that update record
save instance first in some variable:
instance=Partner.where( conditions ).first
then you may access attributes like instance.code and update some attribute
instance.update_attribute || instance.update_attributes
check documentation at api.rubyonrails.org for details

Why Active Record relation is not returned in console?

I have finally started upgrading my Rails apps from 2.3.8 to 3.1.0. I was watching RailsCasts (http://railscasts.com/episodes/202-active-record-queries-in-rails-3) about Active Record queries.
When I open up the console (rails c) and do query similar to this:
articles = Article.order("name")
Instead of returning Active Record relations, I see the query executed. What am I doing wrong here?
Rails version: 3.1.0
RVM on 1.9.2
Thank you for your help!
EDIT: I have added a screenshot from the example.
The ActiveRecord Relation class is configured to perform the query when a query method like .all, .last, .first, ... is invoked. The list of method also includes .inspect, the same method called by the console to display the representation of the return value.
For this reason it seems to you that the object is never a relation, because you always see the result of the query.
But if you inspect the object class, you'll notice it's a relation
Article.order("name").class
# => ActiveRecord::Relation
You're doing everything right. You see query executed because console invokes inspect method on output. Try articles = Article.order("name").class

Problems using ActiveRecord model on existing table

I've created a model for an existing table using the following generator command:
script/generate model Group
The table in question have a different name, so I've changed the model to account for it.
set_table_name 'demandegroupe'
Then I've fired up the console to look if everything was working.
>> Group.all
[#<Group login: "XXXXXX", ...>, ...]
But, to my surprise, using this model in a view throws out weird errors. I returned to the console to make sure I wasn't hallucinating and here's what happened:
>> Group.first
#<Group login: "XXXXXX", ...>
>> Group.first.login
NoMethodError: undefined method `generated_methods' for 50:Fixnum
from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/attribute_methods.rb:247:in `method_missing'
from (irb):2
After that the first expression is not working anymore:
>> Group.first
NoMethodError: undefined method `column_names' for 50:Fixnum
All columns are either varchar or int, where's that 50:Fixnum type is coming from?
Thanks
Are you using Mysql? Group is a reserved sql keyword. It looks like Rails 2.3.5+ handles this for mysql, but it may be causing the problem you're seeing on other databases or other versions of Rails.
Finally, I made a huge mistake, or more precisely overlooked an important detail! It's a simple column name clash, I had review them for potential issues, but missed one buried in the 26 others. That malicious column was named class and once AR generated it's magic code after accessing any column it just replaced the vital class method without throwing any error.
I expected few name clashed as the column names seemed all written in French, so didn't took enough time and must have read "classe" or something like that. Beware the mighty name clash!
Thanks to ehsanul and dmajkic for making me review those column names a second time.

Constructing URL parameters in Rails 3

I am trying to use the following code to convert a hash of options (e.g. { :opt1 => 'a', :opt2 => 'b' } ) into parameters to be appended to a URL (e.g. example.com/page?opt1=a&opt2=b):
ActionController::Routing::Route.new.build_query_string(options)
where options is the hash. I get the following error:
wrong number of arguments (0 for 7)
The corresponding docs show that the initializer method for Route take no arguments, but I think they haven't been updated for Rails 3 yet. I know routing has seen a big update for Rails 3, so I assume this code is for Rails 2.x. Does anyone know what the Rails 3 way of doing this would be?
Thanks
Never mind - I found the answer.
Rails provides a Hash#to_query method (and for some other types too I think).
Somehow Google did a poor job of finding this for me!

Resources