How to collect in Rails? - ruby-on-rails

baza_managers = BazaManager.find(:all,
:conditions => ["or_unit_id != ?", 1]).collect {
|mou| [mou.email, mou.or_unit_id]}
respondent_emails = Respondent.find(:all).collect {|r| r.email }
ERROR:
from lib/scripts/baza_sync.rb:26:in `each'
from lib/scripts/baza_sync.rb:26
26 line ↓
baza_managers.each do |moi|
if !respondent_emails.include?(moi)
Respondent.create(:email => moi, :user_id => 1, :respondent_group_id => moi)
end
end
ERROR I GET:
undefined method `email' for ["vadasd#test.test.com", 8]:Array (NoMethodError)
I don't know why I'm getting this error.

try with:
baza_managers = BazaManager.find(:all,
:conditions => ["or_unit_id != ?", 1]).collect {
|mou| [mou.email, mou.or_unit_id]}
respondent_emails = Respondent.find(:all).collect {|r| r.email }
baza_managers.each do |moi|
if !respondent_emails.include?(moi[0])
Respondent.create(:email => moi[0], :user_id => 1, :respondent_group_id => moi[1])
end
end

Fix your code with following:
if !respondent_emails.include?(moi[0])
Respondent.create(:email => moi[0], :user_id => 1, :respondent_group_id => moi[1])
end

I would think there is at least one error not in the way you are using collect but in the logic you write on the last lines when you go through the baza_managers array.
With this code the condition respondent_emails.include?(moi) will be always false because respondent_emails is an array of email addresses but moi is an array like ["vadasd#test.test.com", 8] so they will never match.
I think this mistake made you make an error in the line :
Respondent.create(:email => moi, :user_id => 1, :respondent_group_id => moi)
Because this line will be evaluate as (for example) :
Respondent.create(:email => ["vadasd#test.test.com", 8], :user_id => 1, :respondent_group_id => ["vadasd#test.test.com", 8])
Which is probably not what you want.
Last, I would suggest you to read the debugger rails guide, I often use debugger to figure out where and what is the problem in this kind of code and error.

I would rewrite your code as follows:
baza_managers = BazaManager.all(:conditions => ["or_unit_id != ?", 1]).
collect { |mou| [mou.email, mou.or_unit_id]}
respondent_emails = Respondent.find(:all).collect {|r| r.email }
baza_managers.each do |email, unit_id|
unless respondent_emails.include?(email)
Respondent.create(:email => email, :user_id => 1,
:respondent_group_id => unit_id)
end
end
This solution can be further optimized by using OUTER JOIN to detect missing Respondents
BazaManager.all(
:include => "OUTER JOIN respondents A ON baza_managers.email = A.email",
:conditions => ["baza_managers.or_unit_id != ? AND A.id IS NULL", 1]
).each do |bm|
Respondent.create(:email => bm.email, :respondent_group_id => bm.or_unit_id,
:user_id => 1)
end
The solution can be made elegant and optimal by adding associations and named_scope.
class BazaManager
has_many :respondents, :foreign_key => :email, :primary_key => :email
named_scope :without_respondents, :include => :respondents,
:conditions =>["baza_managers.or_unit_id != ? AND respondents.id IS NULL", 1]
end
Now the named_scope can be used as follows:
BazaManager.without_respondents.each do |bm|
Respondent.create(:email => bm.email, :respondent_group_id => bm.or_unit_id,
:user_id => 1)
end

Related

Rails splited code not working

I am using rails 2.3. In my application it uses
val = Party.find(:all, :conditions => [" type in ('Physician') || id in (?)",PartyLabel.find(:all,:conditions=>"label_id=#{Label.find_by_label("Can Schedule").id}").collect{|p| p.party_id if Party.find(p.party_id).respond_to?("provider_organizations")}], :with_disabled => true).select{|physician| not physician.provider_organizations.blank? }.collect{|enum| [enum.display_name_schedule, enum.id]}
code to achieve some requirements. Now i wants to split the code in to 2 parts.
1. phys = Physician.find(:all, :include => :provider_organizations, :with_disabled => true).select{|physician| not physician.provider_organizations.blank? }.collect{|enum| [enum.display_name_schedule, enum.id]}
it's working fine.. and the second part will be
2. sch = Party.find(:all, :include => [:as_labels], :conditions => {:label => {:label => "Can Schedule"}}.respond_to?("provider_organizations")).select{|physician| not physician.provider_organizations.blank? }.collect{|enum| [enum.display_name_schedule, enum.id]}
it shows NoMethodError (undefined method 'provider_organizations' for #<ProviderOrganization:0x1ab81c20>): error message... Any comments could be appreciated..
It looks like respond_to?("provider_organizations") is called for a wrong object. Here is your code #2:
sch = Party.find(
:all,
:include => [:as_labels],
:conditions => {
:label => {
:label => "Can Schedule"
}
}.respond_to?("provider_organizations") # What's this ???
).select{ |physician|
not physician.provider_organizations.blank?
}.collect{ |enum|
[enum.display_name_schedule, enum.id]
}
If I understand it correctly, the respond_to? should be inside the select:
...
).select{ |physician|
physician.respond_to?("provider_organizations") && not physician.provider_organizations.blank?
}.collect{ ...

How to loop rails variable?

I have totally nine buttons in rails. I have input the data into the database by manually typing the #button_1.save function.
My question is:
How can i have the #button_i.save function in rails? I have finished the things in the for loop, what is left is the button save functions.
Many thanks!
button_number = params[:button_number]
for i in (1..button_number)
instance_variable_set("#button#{i}",
Button.new(:title => params["button_title_#{i}".to_sym],
:order => i,
:icon_url => params["button_icon_#{i}".to_sym],
:navigation_id => #navigation.id,
:next_navigation => params["selected_navigation_#{i}".to_sym].to_i,
:next_page => params["selected_page_#{i}".to_sym].to_i))
instance_variable_set("#button#{i}")
end
#button1.save
#button2.save
#button3.save
#button4.save
#button5.save
#button6.save
for i in ...
eval("#button#{i}.save")
end
The opposite of instance_variable_set is instance_variable_get, which I think will lead you to the correct answer:
1.upto(params[:button_number].to_i) do |i|
instance_variable_set("#button#{i}",
Button.new(
:title => params["button_title_#{i}".to_sym],
:order => i,
:icon_url => params["button_icon_#{i}".to_sym],
:navigation_id => #navigation.id,
:next_navigation => params["selected_navigation_#{i}".to_sym].to_i,
:next_page => params["selected_page_#{i}".to_sym].to_i
)
)
instance_variable_get("#button#{i}").save
end
Try by using constantize ruby function because I think your function call statement is in string.
button_number = params[:button_number]
for i in (1..button_number)
instance_variable_set("#button#{i}",
Button.new(:title => params["button_title_#{i}".to_sym],
:order => i,
:icon_url => params["button_icon_#{i}".to_sym],
:navigation_id => #navigation.id,
:next_navigation => params["selected_navigation_#{i}".to_sym].to_i,
:next_page => params["selected_page_#{i}".to_sym].to_i))
"#button#{i}".constantize.save();
end
May be this that you want -
button_number = params[:button_number].to_i
for i in (1..button_number)
instance_variable_set("#button#{i}",
Button.new(:title => params["button_title_#{i}".to_sym],
:order => i,
:icon_url => params["button_icon_#{i}".to_sym],
:navigation_id => #navigation.id,
:next_navigation => params["selected_navigation_#{i}".to_sym].to_i,
:next_page => params["selected_page_#{i}".to_sym].to_i))
instance_variable_set("#button#{i}")
"#button#{i}".save
end

rails, syntax error, unexpected ','

I have several conditions in my search.
#events = Event.search(params[:search],
:conditions => {:group_size => 1, :days => 1})
The above code is working fine. However, if I want to replace the hash with a private method, I get syntax error
syntax error, unexpected ',', expecting tASSOC
:conditions => {group_size_condition, :days => 1},
Code is as follow
#events = Event.search(params[:search],
:conditions => {group_size_condition, :days => 1})
private
def group_size_condition
if params[:groupsize] == 'single (1)'
:group_size => 1
elsif params[:groupsize] == 'couple (2)'
:group_size => 2
elsif params[:groupsize] == 'small group(3-5)'
:group_size => 3..5
else
nil
end
end
Thanks in advance
That will be work
#events = Event.search(params[:search],
:conditions => group_size_condition.merge(:days => 1))
private
def group_size_condition
case params[:groupsize]
when 'single (1)' then {:group_size => 1}
when 'couple (2)' then {:group_size => 2}
when 'small group(3-5)' then {:group_size => 3..5}
else
{}
end
end
I think you missed :group_size key
#events = Event.search(params[:search],
:conditions => {:group_size => group_size_condition, :days => 1})
I think perhaps you want to actually pass the string, as in:
def group_size_condition
if params[:groupsize] == 'single (1)'
':group_size => 1'
elsif params[:groupsize] == 'couple (2)'
':group_size => 2'
elsif params[:groupsize] == 'small group(3-5)'
':group_size => 3..5'
else
nil
end
end

How to show foreign key relationship data in jqgrid?

I know how to access foreign key attributes in a scaffold index view. I can simply refer to the attributes using dot notation such as property.que.name. Given the following models:
class Priority < ActiveRecord::Base
belongs_to :que
...
end
class Que < ActiveRecord::Base
has_many :priorities
...
end
In the index view, I can do something like this to get the name value:
<td><%=h priority.que ? priority.que.name : "" %></td>
How do I do this in the jqgrid?
I tried this but the jqgrid comes back empty:
Priorities Controller:
#priorities = Priority.find(:all, :order => "position", :conditions => "multitenant_team_id = " + current_user.team.id.to_s ) do
if params[:_search] == "true"
id =~ "%#{params[:id]}%" if params[:id].present?
issue_id =~ "%#{params[:issue_id]}%" if params[:issue_id].present?
que =~ "%#{params[:que]}%" if params[:que].present?
customer =~ "%#{params[:customer]}%" if params[:customer].present?
title =~ "%#{params[:title]}%" if params[:title].present?
reporting_source =~ "%#{params[:reporting_source]}%" if params[:reporting_source].present?
priority =~ "%#{params[:priority]}%" if params[:priority].present?
product =~ "%#{params[:product]}%" if params[:product].present?
current_owner =~ "%#{params[:current_owner]}%" if params[:current_owner].present?
end
paginate :page => params[:page], :per_page => params[:rows]
order_by "#{params[:sidx]} #{params[:sord]}"
end
if request.xhr?
end
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #priorities.to_jqgrid_json(
[:id, :issue_id, :que.name, :customer, :title, :reporting_source,
:priority, :product, :current_owner],
params[:page], params[:rows], #priorities.total_entries)}
format.xml { render :xml => #priorities }
end
end
Index View:
<%= jqgrid("Priorities", "priorities", "/priorities",
[
{:field => "id", :label => "ID", :width => 35, :resizable => false},
{:field => "issue_id", :label => "Issue Id"},
{:field => "que", :label => "Queue"},
{:field => "customer", :label => "Customer"},
{:field => "title", :label => "Title"},
{:field => "reporting_source", :label => "Reporting Source"},
{:field => "priority", :label => "Priority"},
{:field => "product", :label => "Product"},
{:field => "current_owner", :label => "Current Owner"}
],
{ :rows_per_page => 12, :height => 450 }
)%>
If I specify que instead of que.name, I get the data back in the grid but the Queue field shows a "#" symbol so I suspect the .to_jqgrid_json call doesn't like my syntax.
Has anyone tried this before? I hope so.
I fixed my problem. I ended up changing my find to a find_by_sql so I could do a left outer join on the ques table. I think there were a couple of issues. I think the *to_jqgrid_json* had problems with null foreign key values and I couldn't figure out how to get at the Que.name any other way. I'm using SQLServer so I had to use isnull(ques.name, '') to convert the null to empty space.
So I replaced my find as follows:
#priorities = Priority.find_by_sql ["select priorities.id id, issue_id, isnull(ques.name,' ') queue_name, customer, title, reporting_source, priority, product, current_owner from priorities left outer join ques on priorities.que_id = ques.id where priorities.multitenant_team_id = ? order by issue_id", current_user.team.id.to_s]
This introduced another problem in that find_by_sql returns an array which breaks the #priorities.total_entries call. So I had to replace it with array.count.
format.json { render :json => #priorities.to_jqgrid_json(
[:id, :issue_id, :queue_name, :customer, :title, :reporting_source, :priority, :product, :current_owner],
params[:page], params[:rows], #priorities.count)}
My grid looks great!
Edit
My grid LOOKS great but it doesn't paginate or sort. Back to the drawing board. :(
Okay, I think I fixed it for real this time.
#priorities = Priority.find(:all,
:select => "priorities.id, priorities.issue_id,
priorities.customer, priorities.title,
priorities.reporting_source, priorities.priority,
priorities.product, priorities.current_owner,
priorities.position,
isnull(ques.name,' ') queue_name",
:joins => "LEFT OUTER JOIN ques ON ques.id = priorities.que_id",
:order => "priorities.position",
:conditions => "priorities.multitenant_team_id = " + current_user.team.id.to_s ) do
I had know idea I could specify joins like this. This keeps the resultset in a format the 2dc_jqgrid plugin likes. Sorting, pagination and searching all work now. Now my grid looks good and actually works.

rails active record - complicated conditions clause

this works:
ids = [1,2]
varietals = Varietal.find(:all, :conditions => [ "id IN (?)",ids])
But what I want to do is that plus have a condition of: deleted => false
varietals = Varietal.find(:all, :conditions =>{ :deleted => false})
any ideas?
am i going to have to use find_by_sql?
I would handle this with a named_scope to communicate intent and foster re-use:
named_scope :undeleted,
:conditions => { :deleted => false }
Then you can simply use:
varietals = Varietal.undeleted.find([1,2])
You can do it a few ways, but this is the most straight forward:
varietals = Varietal.find( [1,2], :conditions => { :deleted => false })
You can see in the docs that the first parameter of find can take an integer or an array.
ids = [1,2]
varietals = Varietal.find(:all, :conditions => {:id => ids, :deleted => false})
This should work, haven't tested it though.
From the docs:
An array may be used in the hash to
use the SQL IN operator:
Student.find(:all, :conditions => { :grade => [9,11,12] })

Resources