To allow me to quickly filter records in ActiveAdmin i've defined scopes on my model. I have "shipped" and "unshipped" scopes as below. For some reason the "Shipped" scope is working as expected and shows the number of shipped items but the "Unshipped" scope doesn't do anything, it doesn't seem to know what is unshipped. It seems that i have to check and then uncheck "Shipped" checkbox in order for it to know that it's unshipped??
ORDER MODEL
class Order < ActiveRecord::Base
scope :shipped, where(:shipped => true)
scope :unshipped, where(:shipped => false)
end
ADMIN ORDER MODEL
ActiveAdmin.register Order do
scope :all, :default => true
scope :shipped
scope :unshipped
index do
selectable_column
column "Status", :sortable => :shipped do |s|
status_tag((s.shipped? ? "Shipped" : "Unshipped"), (s.shipped? ? :ok : :warning))
end
end
end
Can anyone see what the problem is?
Many Thanks
Is that the actual code from your model?
It should be:
scope :shipped, -> { where(shipped: true) }
scope :unshipped, -> { where(shipped: false) }
Realised that shipped was not by default set to false so fixed the issue by doing so in the Orders table.
Related
I am using globalize and i18n.
I have the following models:
class Result < ActiveRecord::Base
belongs_to :test
...
scope :sort_with_teaser, lambda { |direction|
joins(test: :test_translations).
where(test_translations: {locale: 'fr'}).
order("test_translations.teaser #{ direction }")
}
end
class Test < ActiveRecord::Base
translates :teaser
...
end
So with Globalize and I18n, I have also a test_translations table.
I want to implement a scope sort_with_teaser inside my Result model to sort result with their result.test.teaser. But I this code doesn't work.
Any help welcome.
Ok I just fixed it :
joins(test: :translations).where(test_translations: {locale: 'fr'}).order("test_translations.teaser #{ direction }")
I have a simple spec testing the creation of an object of the Baseline class.
it "allows a user to create a baseline score with valid content" do
expect(#user.baselines.count).to eq(0)
#baseline = post(:create, :user_id => #user.id, :baseline => valid_attributes)
expect(response).to redirect_to '/patients/list'
expect(flash[:notice]).to eq("Baseline scores for case #{#baseline.case_id} was successfully created.")
expect(Baseline.all.count).to eq(1)
end
But I get this. I am uncertain where to begin with this - I am uncertain why I can't access the case_id attribute of #baseline.
NoMethodError:undefined method `case_id' for <ActionController::TestResponse:0x007f8f5ab4f3c0>
Just to show...these are the valid attributes
let(:valid_attributes) do {
:dx1 => "IPF",
:dxcon1 => 100,
:db1 => "Progressive",
:dbcon1 => 100,
:mgt=> "Drugs",
:biopsy => "Yes",
:patient_id => #patient.id,
:case_id => #patient.case,
}
end
post doesn't return a model instance it returns a TestResponse object which gives you access to headers, status code, etc. To access the object created as a side effect of calling the :create action you can do Baseline.last (in this case Baseline.first would also work since there are no existing baseline objects)
Also note - if you have an instance variable named #baseline that is assigned in the controller you can access that with assigns(:baseline)
expect(assigns[:baseline]).to be_a(Baseline)
I have the following models, which both currently have the same scope:
programme.rb
has_many: :campaigns
scope :visible, -> { where(status: 1) }
camapaign.rb
belongs_to: programme
scope :visible, -> { where(status: 1) }
I would like to edit the campaign scope to only search through the programmes which are visible. Ideally I would like to change that scope to be:
(most likely in a function)
def self.visible
Programme.visible.campaigns.where.(status: 1)
end
But this is returning:
undefined method `campaigns' for #<Programme::ActiveRecord_Relation:0x007f8c9677cd68>
Can someone explain why I can't do this? Also, if any solution to this would be appreciated? preferably without using .joins (But I'll take what I can get at this point)
Thanks
It's hard to tell from your question whether status is an attribute of Programme, Campaign, or both.
Assuming both, you could do this:
# class Programme
has_many :campaigns
scope :visible, -> { where(status: 1) }
# class Campaign
belongs_to :programme
scope :visible, do
joins(:programme).
merge(Programme.visible).
where(status: 1)
end
With this setup, Campaign.visible will only return Campaigns that belong to visible Programmes (and where status == 1, not sure if that means "visible" in your app).
As for why you can't call
Programme.visible.campaigns.where(status: 1)
campaigns is a collection that belongs to a single Programme. It doesn't make sense to ask a collection of Programmes for its campaigns.
I have been using the information here (http://ngauthier.com/2013/08/postgis-and-rails-a-simple-approach.html) so that the search results in my app can be shown based on proximity.
I am listing all tasks with their associated project information - a project can have multiple tasks.
I have the following AR query in my Project controller:
#results = Task.select('tasks.*') # .select('tasks.*') required for pg_search
.joins(:project => :user)
.includes(:project => :user)
.merge(Project.enabled_only.filter_by_location(#geo).search(params[:q]))
.order_results(sort)
In my Project model I have:
scope :distance_from, ->(latitude, longitude) {
select(%{
ST_Distance(
ST_GeographyFromText(
'SRID=4326;POINT(' || projects.longitude || ' ' || projects.latitude || ')'
),
ST_GeographyFromText('SRID=4326;POINT(%f %f)')
) AS distance
} % [longitude, latitude])
}
scope :near, ->(latitude, longitude, distance_in_meters = 1000) {
where(%{
ST_DWithin(
ST_GeographyFromText(
'SRID=4326;POINT(' || projects.longitude || ' ' || projects.latitude || ')'
),
ST_GeographyFromText('SRID=4326;POINT(%f %f)'),
%d
)
} % [longitude, latitude, distance_in_meters])
}
def self.filter_by_location(geo_location)
scoped = self.all
if geo_location.present?
scoped = scoped.distance_from(geo_location[:lat], geo_location[:lng])
scoped = scoped.near(geo_location[:lat], geo_location[:lng])
end
scoped
end
I then have the following in my Task model:
scope :distance_order, -> { order('distance') }
def self.order_results(sort)
# order scopes are appended
scoped = self.all.reorder('')
# check sql for search and distance fields
search_performed = scoped.to_sql.downcase.include?(' pg_search_rank')
distance_calculated = scoped.to_sql.downcase.include?(' distance')
if sort == 'rel'
# rel,dist
scoped = scoped.search_rank_order if search_performed
scoped = scoped.distance_order if distance_calculated
else
# dist,rel
scoped = scoped.distance_order if distance_calculated
scoped = scoped.search_rank_order if search_performed
end
scoped = scoped.name_order
scoped
end
This works fine for my app to sort results by proximity.
Distance is one of the columns in the sql select produced by the AR query, along with tasks.* and distance is being used correctly to sort results but I'm not sure how to display the distance in my view.
If I do <%= result.distance.to_s %>, it says distance is an undefined method. I don't have any joy with <%= result.project.distance.to_s %> either. Whereas <%= result.task_field %> and <%= result.project.project_field %> work fine.
I haven't seen too much use of both .joins() and .includes() at the same time in the RoR world but it did allow me to reduce the number of db calls whilst still producing the correct sql select statement...in my case anyway - that's why they are both used.
Am I missing something?
Is it the complexity of my AR query causing it?
Am I missing something in my Project or Task model to allow the virtual/calculated distance field to be display-able?
Thanks
The complex structure was replaced by a database view.
More details of how to do this can be found at this tutorial (http://pivotallabs.com/database-views-performance-rails/) and in one of my other SO questions here (Connecting database view with polymorphic model in rails).
When defining column_names in a counter_culture method, is it possible to deeply associate? In the docs and examples its always an attribute belonging to the model that is used to determine column_names. But, what if the attribute belongs to an associated model?
example, this works
# Account model
counter_culture :user,
column_name: Proc.new { |account| account.has_billable_hours? ? 'billed_hours_sum' : nil },
delta_column: 'billed_hours',
column_names: { ["account.billed_hours > ?", 0] => "billed_hours_sum" }
associated example
# Account model
counter_culture :user,
column_name: Proc.new { |account| account.clients.has_billable_hours? ? 'billed_hours_sum' : nil },
delta_column: 'billed_hours',
column_names: { ["accounts.clients.billed_hours > ?", 0] => "billed_hours_sum" }
If, for the above, you could (you can't) use joins in the column_names method it would look like this
joins(:account=>:client).where("accounts.clients.billed_hours > ?", 0)
The second example illustrates my question. How do you define the column_names when the attribute you need to evaluate does not belong to the parent model, but an associated model?
column_names is only need when calling counter_culture_fix_counts. So, I just 86'ed the column_names option from the the method call and created a rake task to update that counter/column manually.