Rails4 Deprecation Warning - ruby-on-rails-4

Rails4 is getting depreciation warning when I am upgrading from rails 3.2 to rails 4.0. I have this query.
Child.find(:all, :include => :children_users, :conditions => "state = 'active' AND owner_id = #{self.id} AND children_users.user_id = #{other_user.id}")
I am getting deprecation warning as follow :-
DEPRECATION WARNING: It looks like you are eager loading table(s) (one of: splits, accounts) that are referenced in a string SQL snippet. For example:
Post.includes(:comments).where("comments.title = 'foo'")
Currently, Active Record recognizes the table in the string, and knows to JOIN the comments table to the query, rather than loading comments in a separate query. However, doing this without writing a full-blown SQL parser is inherently flawed. Since we don't want to write an SQL parser, we are removing this functionality. From now on, you must explicitly tell Active Record when you are referencing a table from a string:
Post.includes(:comments).where("comments.title = 'foo'").references(:comments)
If you don't rely on implicit join references you can disable the feature entirely by setting `config.active_record.disable_implicit_join_references = true`. (called from splits_under_100_percent at /Users/newimac/RailsApp/bank/app/models/user.rb:274)
To solve this problem, I have try like this
Child.includes(:children_users).where(state: active, owner_id: self.id, children_users.user_id = other_user.id).load
or
Child.where{(state: active, owner_id: self.id, children_users.user_id = other_user.id).includes(:children_users)}
But none of them work.

children_users.user_id = other_user.id wrong.
The correct one is: "children_users.user_id" => other_user.id

Thank You for #Zakwan. Finally, this query works.
Child.includes(:children_users).where(state: 'active', owner_id: self.id, "children_users.user_id" => other_user.id).load

Related

Rails 4 Has_Many With Finder_SQL Deprecated

I am upgrading a Rails app to 4.0. I am receiving the following deprecation warning. I have Google'd on this, but have not found anything that tells how to change this.
DEPRECATION WARNING: The :finder_sql association option is deprecated. Please find an alternative (such as using scopes)...
Here is the scope that is causing the warning:
has_many :elective_instructors,
:class_name => "Instructor",
:finder_sql => proc { "SELECT DISTINCT people.* FROM people
INNER JOIN class_sections ON class_sections.instructor_id = people.id
INNER JOIN courses ON courses.id = class_sections.course_id
INNER JOIN taken_classes ON class_sections.id = taken_classes.class_section_id
WHERE
courses.core = FALSE
AND
taken_classes.student_id = #{id}
AND
people.type = 'Instructor'
AND
people.ignore = FALSE" }
Any ideas would be greatly appreciated. Thanks!
As of 4.1, :finder_sql is not just deprecated - it has been completely REMOVED from Rails.
Here is one way to do something similar through the use of scopes. Let's say we have a User class and Job class (so a user can have many jobs). And let's say that we want to find all distinct jobs that this user holds (contrived example, but it illustrates the point) and let's say we want to use custom SQL for this. We can use find_by_sql as follows
class Job < ActiveRecord::Base
scope :distinct_user_jobs, -> (user_id){ find_by_sql(["SELECT DISTINCT jobs.* FROM jobs WHERE jobs.user_id=?", user_id]) }
end
And then pass in the user_id
user = User.first
Job.distinct_user_jobs(user.id)

How to create a model without controller considering rails4 strong parameters

Cannot find anywhere the accepted way to create a model without going through controller considering that attr_accissible is no longer supported.
Is the below approach correct?
in my old code:
ModelName.create(course_id:680, user_id:25)
(raises mass_assignment error now that I have removed attr_accessible)
new code:
model = ModelName.new.tap do |m|
m.course_id = 680
m.user_id = 25
end
model.save!
(works but looks hacky)
Apparently, the below will not work because without_protection option is removed in Rails4
ModelName.create({course_id: 680, user_id: User.first.id}, without_protection: true)
Thanks to this question I've read about strong parameters 'Use outside of Controllers' - link but even if I do the following from my console:
raw_params = {course_id: Course.last.id, user_id: User.first.id}
parameters = ActionController::Parameters.new(raw_params)
ModelName.create(parameters.permit(:course_id, :user_id))
I get error
WARN -- : WARNING: Can't mass-assign protected attributes for ModelName: course_id, user_id
I read this question more carefully and found my answer
I had to add
config.active_record.whitelist_attributes = false
to my environments (development/test/production.rb), maybe because I still have the protected_attributes gem installed.
so now I can happily use
ModelName.create(course_id:680, user_id:25)
afterall.
I realise this question/answer is somewhat of a repeat of the aforementioned question - but I did find that question a bit tricky to understand, so I won't take this question down unless asked.

Django .get() raises DoesNotExist error without explicit '__exact' lookup

I've faced with issue, which I cannot neither understand nor 'google', while followed steps from "Practical Django Projects" book.
The example of view code below should return specific Entry object (I omitted unnecessary part), but it raises "DoesNotExist: Entry matching query does not exist" error:
...
return render_to_response('weblog/entry_detail.html',
{'entry':Entry.objects.get(pub_date__year=pub_date.year,
pub_date__month=pub_date.month,
pub_date__day=pub_date.day,
slug=slug)
(I confirmed that target object indeed exists, etc.)
When I replaced .get() with filter() method, it returned me queryset with my target object.
After some 'hitting-the-wall' sessions, I managed to make .get() call work when replaced
slug=slug
with
slug__exact=slug
I cannot get the difference between these two. Seems to me, Django's docs clearly state that in such case '__exact' is implied (Django 1.6, "Making queries")
I also cannot check the actual SQL query which Django ran in the .get() cases to compare with SQL query used with .filter() method (the result is either object, not queryset, or raised exception).
So, I actually have 2 workarounds (filter()[0] to get single object, or '__exact'), but I want to understand the weird behavior with .get() method.
My questions are:
Did I misunderstand documentation about '__exact' implication in my case?
If no, isn't my problem a Django/DB bug?
Is there a way to check the actual SQL query which Django has performed, when result of query is not a queryset object?
Thank you!
Note: I run Django 1.6.1 / Python 2.7.3 / MySQL 5.5.33
Update: I installed suggested django-debug-toolbar and was able to compare queries for .get() call with & w/o '__exact' lookup. The only difference that I see between these queries, is the order of 'AND' conditions, so still have no clue what's going on:
slug=slug:
SELECT weblog_entry.id, weblog_entry.title, weblog_entry.excerpt, weblog_entry.body, weblog_entry.pub_date, weblog_entry.excerpt_html, weblog_entry.body_html, weblog_entry.author_id, weblog_entry.slug, weblog_entry.status, weblog_entry.enable_comments, weblog_entry.featured FROM weblog_entry WHERE (EXTRACT(MONTH FROM CONVERT_TZ(weblog_entry.pub_date, 'UTC', 'UTC')) = 2 AND weblog_entry.pub_date BETWEEN '2014-01-01 00:00:00' and '2014-12-31 23:59:59' AND EXTRACT(DAY FROM CONVERT_TZ(weblog_entry.pub_date, 'UTC', 'UTC')) = 2 AND weblog_entry.slug = '3rd-entry' )
slug__exact=slug:
SELECT weblog_entry.id, weblog_entry.title, weblog_entry.excerpt, weblog_entry.body, weblog_entry.pub_date, weblog_entry.excerpt_html, weblog_entry.body_html, weblog_entry.author_id, weblog_entry.slug, weblog_entry.status, weblog_entry.enable_comments, weblog_entry.featured FROM weblog_entry WHERE (EXTRACT(MONTH FROM CONVERT_TZ(weblog_entry.pub_date, 'UTC', 'UTC')) = 2 AND weblog_entry.pub_date BETWEEN '2014-01-01 00:00:00' and '2014-12-31 23:59:59' AND weblog_entry.slug = '3rd-entry' AND EXTRACT(DAY FROM CONVERT_TZ(weblog_entry.pub_date, 'UTC', 'UTC')) = 2)
Note: I've tried to execute these queries manually from mysql console and they both selected target entry;
Update2: I've changed title to point on the problem more precisely.
Ok, let me speak for collective unconscious.
Did I misunderstand documentation about '__exact' implication in my case?
No, you got it right. Let me quote django doc:
As a convenience when no lookup type is provided (like in
Entry.objects.get(id=14)) the lookup type is assumed to be exact.
And since you observe something that contradicts requirements, answer to the next question is:
If no, isn't my problem a Django/DB bug?
Yes, it is a bug. Me and whole Django community will be grateful if you describe steps to reproduce and file an issue
Is there a way to check the actual SQL query which Django has
performed, when result of query is not a queryset object?
Looks you already got the answer :)

Error 404 when i use ActiveResource with Redmine

i have a problem with redmine. In fact, i've created a model who use ActiveResource :
require 'active_resource'
class New < ActiveResource::Base
#self.site = "http://localhost:3000/"
#self.format = :xml
#self.user = 'admin'
#self.password = 'admin'
class << self
attr_accessor :api_key
end
def save
prefix_options[:api_key] = self.class.api_key
super
end
end
New.site = 'http://localhost:3000'
New.api_key = '471bea6d1c4452b82b57287a281ff04392ae4118'
nw = New.new(:field_1 => 'value 1')
nw.save
# Retrieving news
news = New.find(:all)
puts news.first.title
#Retrieving an new
new = New.find(1)
puts new.description
puts new.author.name
# Creating an new
new = New.new(
:project_id => 1,
:author_id => 1,
:title => 'Annonce',
:summary => 'Annonce',
:description => 'Annonce'
)
if new.save
puts new.id
else
puts new.errors.full_messages
end
# Updating an 'new'
new = New.find(1)
new.title = 'NEW INFO '
new.save
# Deleting an new
new = New.find(1)
new.destroy
I'v an error 404 and i don't understand why:
/Users/bj/.rvm/gems/ruby-1.9.3-p429/gems/activeresource-4.0.0/lib/active_resource/connection.rb:144:in `handle_response': Failed. Response code =404. Response message = Not Found . (ActiveResource::ResourceNotFound)
PS: If i use api key or if i use self.site i've a 404 too !
Can you help me please? I tried many things but no every things doesn't works. Thanks for your answers !
The basic problem seems to be, that Redmine is not responding the way ActiveResource expects it. This could be due to changes in Rails 3, that where not properly reflected in Redmine yet.
The best option for you would maybe be dropping ActiveResource for something like httparty. You should also known, that Redmine currently only supports fetching all news (/news.json) and all news within a project (/projects/test_project/news.json). Neither fetching a single news directly nor creating or updating news is supported via the REST API.
Edit: The actual cause for the 404 in your code is due to the fact, that ActiveResource tried to POST to /news.json which is - as I have mentioned above - not supported by the REST API. If you remove the save call, you will run into another issue, where ActiveResource is not able to deserialize the response in New.find(:all). This lead me to think, that Redmine and ActiveResource are currently incompatible. Also the demo code in the Redmine wiki to create an issue, does not work for me.

Rails: Invalid single-table inheritance type error

So, I am working on migrating this php site with an existing database which I cannot change over to Rails. There is a table: Quotes with a column named type. Whenever I try and create a model of this and set the type, it tells me the following error:
ActiveRecord::SubclassNotFound (Invalid single-table inheritance type: HOME is not a subclass of Quotes)
I don't understand why it thinks its inheriting because it's not supposed to. My create method looks like this:
quote = Quotes.create(
agent_id: agent.id,
client_id: client.id,
type: 'HOME',
status: 0,
date_created: DateTime.now
)
If I comment out the type, everything works fine. But with the Type it errors.
I resolved this by setting the models inheritance_column to nil. Active Record Models can inherit from a table through the attribute :type, setting the inheritance_column to nil removes that attribute allowing you to have a database column named type
class Quote < ActiveRecord::Base
self.inheritance_column = nil
end
I hate having potential gotchas deep in the code especially in the intial processes like generating a model. Better to just change the reserved word to something else and free yourself up to take advantage of inheritance column later if the need comes up. A cleaner solution is listed here -> rename a database column name using migration
It reads;
Execute $> rails generate migration ChangeColumnName
where, ChangeColumnName is the name of our migration. This can be any name.
Now, edit the generated migration file at db/migrate/_change_column_name.rb
class ChangeColumnName < ActiveRecord::Migration
def change
rename_column :table_name, :old_column, :new_column
end
end
$> rake db:migrate
You will have to edit controller and view files e.g. if the model name is Product then you will likely edit these files
/app/views/products/_form.html.erb
/app/views/products/show.html.erb
/app/controllers/products_controller.erb
/app/views/products/index.html.erb