Doing just one query search, saving it to an array and then search only the array instead of doing multiple sql queries - sql

i have this
class PagesController < ApplicationController
def index
#textos = Texto.all
#texto_historia = Texto.where(:title => "História").first.contents
#texto_capas_para_sofa = Texto.where(:title => "Capas para Sofá").first.contents
#texto_cortinas = Texto.where(:title => "Cortinas").first.contents
#texto_almofadas = Texto.where(:title => "Almofadas").first.contents
end
The SQL output is:
←[1m←[36mTexto Load (2.0ms)←[0m ←[1mSELECT "textos".* FROM "textos"←[0m
←[1m←[35mTexto Load (1.0ms)←[0m SELECT "textos".* FROM "textos" WHERE ("textos"."title" = 'Hist├│ria') LIMIT 1
←[1m←[36mTexto Load (0.0ms)←[0m ←[1mSELECT "textos".* FROM "textos" WHERE ("textos"."title" = 'Capas para Sof├í') LIMIT 1←[0m
←[1m←[35mTexto Load (1.0ms)←[0m SELECT "textos".* FROM "textos" WHERE ("textos"."title" = 'Cortinas') LIMIT 1
←[1m←[36mTexto Load (1.0ms)←[0m ←[1mSELECT "textos".* FROM "textos" WHERE ("textos"."title" = 'Almofadas') LIMIT 1←[0m
←[1m←[35mTexto Load (0.0ms)←[0m SELECT "textos".* FROM "textos" WHERE ("textos"."title" = 'Informa├º├╡es de Contato') LIMIT 1
What i want is to do just one query for all "textos" model and then search inside an array or anything like that to get the specific variable.

You will need to get the array of all ActiveRecord objects and convert it into a hash storing the data you need.
#textos = Texto.all.inject({}) {|h, obj| h[obj.title] = obj.contents; h }
Then you will be able to access your contents with #textos["title"].

I think you want the find or find_all option:
#texto_historia = #texto.find { |a| a.title = "História"}

Related

How to remove "id" from json string in ruby on rails?

I have got data without "id" field from database. But when I parse the data to json string and show it on screen, I saw an "id" field on json string. How to remove this "id" field?
Here is my code:
-report_logic.rb
def fetch_data ()
#datalist=WorkEarlyOverTime
#datalist = #datalist.joins("INNER JOIN `works` ON `work_early_over_times`.`work_id` = `works`.`id`")
#datalist = #datalist.select('`work_early_over_times`.work_id AS 1次協力会社名','`work_early_over_times`.working_temp_person AS 職種名','`work_early_over_times`.working_temp_hour AS 作業場所','`work_early_over_times`.at_time_overtime_start AS 作業内容','`works`.`contents`')
#datalist = #datalist.where(work_id: $work_id)
return #datalist
end
- report_controller.rb
def work_late
report_logic = ReportLogic.new(params)
#work_late = report_logic.fetch_data()
render action: :work_late
end
- work_late.json.jbuilder
json.一覧 #work_late
When I show the string I expected the output is:
{"一覧":[
{"1次協力会社名":1,
"職種名":"0",
"作業場所":"0.00 ",
"作業内容":"2000-01-01T19:00:00.000+00:00",
"contents":"作業内容1"}
]}
but the actual output is:
{"一覧":[
{"id":null,
"1次協力会社名":1,
"職種名":"0",
"作業場所":"0.00 ",
"作業内容":"2000-01-01T19:00:00.000+00:00",
"contents":"作業内容1"}
]}
As your desired output is a JSON, you could try .as_json by excepting the id field as follows:
#datalist.select('`work_early_over_times`.work_id AS 1次協力会社名','`work_early_over_times`.working_temp_person AS 職種名','`work_early_over_times`.working_temp_hour AS 作業場所','`work_early_over_times`.at_time_overtime_start AS 作業内容','`works`.`contents`').as_json(:except => :id)
Your detailed fetch_data function will be like this:
def fetch_data ()
#datalist=WorkEarlyOverTime
#datalist = #datalist.joins("INNER JOIN `works` ON `work_early_over_times`.`work_id` = `works`.`id`")
#datalist = #datalist.select('`work_early_over_times`.work_id AS 1次協力会社名','`work_early_over_times`.working_temp_person AS 職種名','`work_early_over_times`.working_temp_hour AS 作業場所','`work_early_over_times`.at_time_overtime_start AS 作業内容','`works`.`contents`').as_json(:except => :id)
#datalist = #datalist.where(work_id: $work_id)
return #datalist
end
If id is always null then just ignore all nils:
json.ignore_nil!
json.一覧 #work_late
If that's not the case then you have to filter out the id before serializing it. One way would be:
json.一覧 #work_late.serializable_hash.except("id")

Concurency between 2 where() clause with rails?

I have in my seed.rb something like :
c1 = Chapter.where(number: 1).first_or_create
a1 = Article.where(number: 1, text: 'foo bar' chapter: c1).first_or_create
a2 = Article.where(number: 2, text: 'foo bar baz', chapter: c1).first_or_create
and in Article class :
class Article
belongs_to :chapter
before_create do
self.foo = true if Article.where(chapter_id: chapter_id).count == 0
# I tried this version too, same problem : self.foo = true if chapter.articles.count == 0
end
end
the query excepted to count is :
SELECT COUNT(*) FROM articles WHERE `articles`.`chapter_id` = 1
BUT, SQL log, I have :
for the first article :
SELECT COUNT(*) FROM articles WHERE `articles`.`number` = 1 AND `articles`.`text` = "foo bar" AND `articles`.`chapter_id` = 1 AND (`articles`.`chapter_id` = 1)
and for the second article :
SELECT COUNT(*) FROM articles WHERE `articles`.`number` = 2 AND `articles`.`text` = "foo bar baz" AND `articles`.`chapter_id` = 1 AND (`articles`.`chapter_id` = 1)
My problem is before_createis call before create, so the where in seed.rb is alwais in cache and is combinate with the where in query to count...
So the count are alwais equals to 0, so foo property alwais set at true for all articles
How can I do an independant query?

ActiveRecord has_many with multiple conditions

I'm trying to find an object by checking for several of its relations.
Loan.joins(:credit_memo_attributes)
.where(credit_memo_attributes: {name: 'pr2_gtx1_y', value: '2014'})
.where(credit_memo_attributes: {name: 'pr1_gtx1_y', value: '2013'})
.where(credit_memo_attributes: {name: 'tx1_y', value: '2014'})
Calling to_sql on that gives:
"SELECT `loans`.* FROM `loans` INNER JOIN `credit_memo_attributes`
ON `credit_memo_attributes`.`loan_id` = `loans`.`id`
WHERE `credit_memo_attributes`.`name` = 'pr2_gtx1_y' AND `credit_memo_attributes`.`value` = '2014'
AND `credit_memo_attributes`.`name` = 'pr1_gtx1_y' AND `credit_memo_attributes`.`value` = '2013'
AND `credit_memo_attributes`.`name` = 'tx1_y' AND `credit_memo_attributes`.`value` = '2014'"
So, I'm checking for Loans that have credit_memo_attributes with all of those attributes. I know at least 1 of our 20,000 loans meets this criteria, but this query returns an empty set. If I only use 1 of the where clauses, it returns several, as I'd expect, but once I add even 1 more, it's empty.
Any idea where I'm going wrong?
Update:
Based on comments I believe you want multiple joins in your criteria. You can do that like this:
attr_1 = {name: 'pr2_gtx1_y', value: '2014'}
attr_2 = {name: 'pr1_gtx1_y', value: '2013'}
attr_3 = {name: 'tx1_y', value: '2014'}
Loan.something_cool(attr_1, attr_2, attr_3)
class Loan < ActiveRecord::Base
...
def self.something_cool(attr_1, attr_2, attr_3)
joins(sanitize_sql(["INNER JOIN credit_memo_attributes AS cma1 ON cma1.loan_id = loans.id AND cma1.name = :name AND cma1.value = :value", attr_1]))
.joins(sanitize_sql(["INNER JOIN credit_memo_attributes AS cma2 ON cma2.loan_id = loans.id AND cma2.name = :name AND cma2.value = :value", attr_2]))
.joins(sanitize_sql(["INNER JOIN credit_memo_attributes AS cma3 ON cma3.loan_id = loans.id AND cma3.name = :name AND cma3.value = :value", attr_3]))
end
If you look at the SQL generated (that you included in your question, thank you) you'll see that all those conditions are being ANDed together. There are NO rows for which name = 'pr2_gtx1_y' AND name = 'pr1_gtx1_y' (and so forth). So you are getting the result I would expect (no rows).
You can put all names and values into array like ids and years and pass those into where clause like this. Active Record will query all the values in the array.
Loan.joins(:credit_memo_attributes)
.where(credit_memo_attributes: {name: ids, value: years})
Personally I'm still learning active record, in this concern i don't think active record supports multiple where clauses.
Notice how the SQL version is returning your code: it is joining the requirements with an AND.
"SELECT `loans`.* FROM `loans` INNER JOIN `credit_memo_attributes`
ON `credit_memo_attributes`.`loan_id` = `loans`.`id`
WHERE `credit_memo_attributes`.`name` = 'pr2_gtx1_y' AND `credit_memo_attributes`.`value` = '2014'
AND `credit_memo_attributes`.`name` = 'pr1_gtx1_y' AND `credit_memo_attributes`.`value` = '2013'
AND `credit_memo_attributes`.`name` = 'tx1_y' AND `credit_memo_attributes`.`value` = '2014'"
Now, this is next to impossible. An Object.name can never be all pr2_gtx1_y, pr1_gtx1_y, and tx1_y. Same goes for the value attributes.
What you need here is an OR as opposed to the AND.
To this effect, try to change your query to the following:
Loan.joins(:credit_memo_attributes)
.where(
"credit_memo_attributes.name = ? and credit_memo_attributes.value = ?
OR credit_memo_attributes.names = ? and credit_memo_attributes.value = ?
OR credit_memo_attributes.name = ? and credit_memo_attributes.value = ?",
'pr2_gtx1_y', '2014',
'pr1_gtx1_y', '2013',
'tx1_y', '2014'
)

Ruby on Rails value by association

I have this freeform SQL that when run returns the name of a product, name of the associate attribute and the value for that attribute. What I am trying to work out is how I can use the with Ruby on Rails and Active Record
Freeform Query
select menu_items.name, menu_attributes.name, menu_attributes_items.menu_attribute_value from menu_attributes, menu_items, menu_attributes_items, venues
where menu_items.id = menu_attributes_items.menu_item_id
and menu_attributes.id = menu_attributes_items.menu_attribute_id
and venues.id = menu_attributes_items.venue_id
and menu_attributes.name = 'Price'
This is my current HAMl Template, though it only returns a list of the attributes i.e. Price, Size and not the values like the SQL does
- for item in #venue.menu_items
.grid-content
.card
= image_tag("drinks/#{item.name.titlecase.tr(' ','-')}.png")
%img{:src => "http://placehold.it/400x200?text=Coffee"}
.card-divider
= item.name
.card-section
%h4
- for attr in item.menu_attributes
= attr.name
= MenuItem.joins({ menu_attributes: :menu_attributes_items }, :venues).where('menu_items.id = menu_attributes_items.menu_item_id AND menu_attributes.id = menu_attributes_items.menu_attribute_id AND menu_attributes.id = menu_attributes_items.menu_attribute_id AND venues.id = menu_attributes_items.venue_id AND menu_attributes.name = ?', 'Price').select('menu_items.name, menu_attributes.name, menu_attributes_items.menu_attribute_value')
Updates
Price # Size # Size #
Depending on the associations among your models and still with a slight touch of SQL, your query can be written with ActiveRecord this way:
MenuItem.joins({ menu_attributes: :menu_attributes_items }, :venues)
.where('menu_items.id = menu_attributes_items.menu_item_id AND menu_attributes.id = menu_attributes_items.menu_attribute_id AND menu_attributes.id = menu_attributes_items.menu_attribute_id AND venues.id = menu_attributes_items.venue_id AND menu_attributes.name = ?', 'Price')
.select('menu_items.name, menu_attributes.name, menu_attributes_items.menu_attribute_value')

NHibernate 3.0 - Only one expression can be specified in the select list when the subquery is not introduced with EXISTS."

We are trying to upgrade to NHibernate 3.0 and now i am having problem with the following Linq query. It returns "Only one expression can be specified in the select list when the subquery is not introduced with EXISTS." error.
This is the linq query in the controller.
var list = (from item in ItemTasks.FindTabbedOrDefault(tab)
select new ItemSummary
{
Id = item.Id,
LastModifyDate = item.LastModifyDate,
Tags = (from tag in item.Tags
select new TagSummary
{
ItemsCount = tag.Items.Count,
Name = tag.Name
}).ToList(),
Title = item.Title
});
and the following is the sql generated for this query
select TOP ( 1 /* #p0 */ ) item0_.Id as col_0_0_,
item0_.LastModifyDate as col_1_0_,
(select (select cast(count(* ) as INT)
from dbo.ItemsToTags items3_,
dbo.Item item4_
where tag2_.Id = items3_.Tag_id
and items3_.Item_id = item4_.Id),
tag2_.Name
from dbo.ItemsToTags tags1_,
dbo.Tag tag2_
where item0_.Id = tags1_.Item_id
and tags1_.Tag_id = tag2_.Id) as col_2_0_,
item0_.Title as col_3_0_ from dbo.Item item0_ order by item0_.ItemPostDate desc
ps:If i remove the Tags property in the linq query, it works fine.
Where is the problem in the query?
Thanks in advance.
I've got the same Generic ADO Exception error, I think it's actually the limitation of SQL server;
Is it possible somehow load object graph with projections in collections?
If I try this one:
var cats = q.Select(t => new cat()
{
NickName = t.NickName,
Legs = t.Legs.Select(l => new Leg()
{
Color = l.Color,
Size = l.Size
}).ToList()
}).ToList();
That does the same error..