rails 1 to 4 upgrading the :include keyword - ruby-on-rails-4

I have a whole bunch of Rails 1 code that uses this syntax in models:
...
has_many :widgets, :class_name => 'WidgetAssertion',
:include => [ :activity, :priority_assertion_type ]
...
Rails 4 throws an exception:
(ArgumentError in WhateverController#index)
(Unknown key: :include. Valid keys are: :class_name, :class, :foreign_key,
:validate, :autosave, :table_name, :before_add, :after_add, :before_remove,
:after_remove, :extend, :primary_key, :dependent, :as, :through, :source,
:source_type, :inverse_of, :counter_cache, :join_table, :foreign_type)
How can I port this to Rails 4?

The 2nd argument of has_many is scope:
You can pass a second argument scope as a callable (i.e. proc or lambda) to retrieve a specific set of records or customize the generated query when you access the associated collection.
So, in your example, you could do this:
has_many :widgets, -> { includes(:activity, :priority_assertion_type) },
class_name: 'WidgetAssertion'

Related

RSpec: undefined method for #<ActionController::TestResponse. Testing a dynamic flash message

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)

serve static views from subdirs using a single controller in rails 4

If have some static pages in a tree structure. The ones at the first level are served using static_pages_controller.rb and in my routes.rb I have :
get '/static_pages/news' , :to => 'static_pages#news' , :as => 'news'
get '/static_pages/index' , :to => 'static_pages#index' , :as => 'index'
....
The above exist in
app\views\static_pages\news.html.erb
app\views\static_pages\index.html.erb
....
Now, I pasted some other static pages underneath the static_pages root:
app\views\static_pages\ermis\news.html.erb
app\views\static_pages\ermis\index.html.erb
....
I added in routes.rb this:
get '/static_pages/ermis/news' , :to => 'static_pages#news' , :as => 'news'
get '/static_pages/ermis/index' , :to => 'static_pages#index' , :as => 'index'
The above doesnt work because the actions already exist (parent folders). So I went the painful step of renaming the files to (there must be a better way though?!?)
app\views\static_pages\ermis\ermisnews.html.erb
app\views\static_pages\ermis\ermisindex.html.erb
....
and my routes.rb became
get '/static_pages/ermis/news' , :to => 'static_pages#ermisnews' , :as => 'ermisnews'
get '/static_pages/ermis/index', :to => 'static_pages#ermisindex', :as => 'ermisindex'
....
the controller is empty
class StaticPagesController < ApplicationController
end
Why cant the pages be served ? what am I missing?
When I click on
<%= link_to("Ermis", ermisnews_path, class: 'pictureTitle') %>
I get
"The action 'ermisnews' could not be found for StaticPagesController"
Here my routes.rb
Prefix Verb URI Pattern Controller#Action
root GET / static_pages#index
ermisindex GET /static_pages/ermis/index(.:format) static_pages#ermisindex
ermisnews GET /static_pages/ermis/news(.:format) static_pages#ermisnews
news GET /static_pages/news(.:format) static_pages#news
index GET /static_pages/index(.:format) static_pages#index
NOTE: I do not get an error when using link directly pointing to .erb files on static_pages
<%= link_to("News" , news_path , class: 'pictureTitle')
Question:
1) How can I use the same controller to also serve static pages underneath /static_pages eg. /static_pages/ermis
2) Am I obliged to actually rename the files to have them represent unique actions?
In route.rb, change your routes as:
resources :static_pages do
resources :ermis do
get 'ermisnews' , :on => :collection
end
end
match '/ermisnews' => 'static_pages#ermisnews', :as => :news
And then run rake routes.
Eventually I found a solution to my issue:
created the following namespace:
namespace :sp do
resources: ixanos
resources: ermis
end
created the following controllers
class Sp::IxanosController < ApplicationController
end
class Sp::ErmisController < ApplicationController
end
Placed the controllers under app/controllers/sp/
Created the directories app/views/sp/ixanos and app/views/sp/ermis and copied my files in them.
(*) This way I can have as many static pages as I want underneath the given roots (ermis and ixanos). I haven't tested the situation whereby I will have sub-directories like sp/ermis/dir1/dir2 ...

Rails Fabricator gem with mongoid has_many_and_belongs_to relationship

I'm trying to fabricate a class that has nested elements and has HMABT relationship with another class. Here are my classes
class Quote
has_and_belongs_to_many :providers
belongs_to :user
class Provider
has_and_belongs_to_many :quotes
belongs_to :user
embeds_many :workdones
class Workdone
embedded_in :provider
embeds_many :prices
class Price
embedded_in :workdone
These are my fabricators
Fabricator(:price) do
workdone
variation_id {Fabricate(:variation)._id}
price {12}
discount {5}
end
usern = Faker::Name.last_name
uidn = Faker::Number.number(10)
Fabricator(:user) do
uid 123456
username {usern }
email {Faker::Internet.email}
username_or_uid { [ usern , uidn] }
provider {'facebook'}
name {Faker::Name.name }
gender {'male'}
birthday { Time.at(rand * (18.years.ago.to_f - 50.years.ago.to_f) + 50.years.ago.to_f).to_date }
end
Fabricator(:workdone) do
provider
workdonecount {1}
quotegivencount {1}
rating {5}
active {true}
give_price {true}
end
Fabricator(:provider) do
user
business_address {"Bostanlı Mh., 6352. Sokak No:15, 35480 İzmir, Türkiye"}
business_description {"Biz de sadece epilasyon işleriyle uğraşıyoruz ve bu işlerin
quote(count: 1)
Fabricator(:quote) do
user
providers(count: 3) { Fabricate(:price).workdone.provider }
share_on_facebook_timeline {false}
customer_address {"Bostanlı Mh., 6352. Sokak No:15, 35480 İzmir, Türkiye"}
description {"dasdsadasdsad sadadsssssdsadsasdas"}
location {[27.094637499999976,38.4621336 ] }
variation_id { Fabricate(:variation)._id}
end
When I fabricate quote with Fabricate(:quote)
It gives out this error message
Quote#give_quote works
Failure/Error: Unable to find matching line from backtrace
SystemStackError:
stack level too deep
When I remove quote(count: 1) from provider fabricator it gives out this error.
This works on rails console by the way - providers are created.
Failure/Error: quote = Fabricate(:quote)
TypeError:
no implicit conversion of nil into String
# ./spec/fabricators/quote_fabricator.rb:4:in `block (2 levels) in <top (required)>'
# ./spec/models/quote_spec.rb:51:in `block (3 levels) in <top (required)>'
When I completely remove the providers(count: 3) { Fabricate(:price).workdone.provider }
association from quote fabricator tests pass but of course providers are not created
Does anyone have idea how I can create providers?
Would it be possible to pull three providers from the generated user for this quote? You could do so with the below Fabricator definition.
Fabricator(:quote) do
user
providers { |attrs| attrs[:user].providers.sample(3) }
share_on_facebook_timeline false
customer_address "Bostanlı Mh., 6352. Sokak No:15, 35480 İzmir, Türkiye"
description "dasdsadasdsad sadadsssssdsadsasdas"
location [27.094637499999976,38.4621336]
variation_id { Fabricate(:variation)._id }
end
Also, you only need to use the block syntax if you are dynamically generating values. In the case of all your static values, just passing them in directly (as in the above) will give you a little less overhead.

Scope not working in ActiveAdmin ROR

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.

Count an Attribute on a nested form?

Rails 3.2.12 and Ruby 1.9.3 and Haml
I would like to use the count of attribute to control the display of a 'link_to "remove"', but I am having problems with setting up the logic.
Following is some code from my form as it is currently:
.field
= codeline.label :name, "Units Alloc"
%br/
= codeline.text_field :units_alloc, :precision => 6, :scale => 2, :size => 10,
:class => "ui-state-default"
= codeline.hidden_field :_destroy
= link_to "remove", '#', class: "remove_fields"
this works well but I have the 'remove' link showing up and I would prefer it to only show if there are two :units_alloc attributes.
This is what I tried:
.field
= codeline.label :name, "Units Alloc"
%br/
= codeline.text_field :units_alloc, :precision => 6, :scale => 2, :size => 10,
:class => "ui-state-default"
- if :units_alloc.count > 1
= codeline.hidden_field :_destroy
= link_to "remove", '#', class: "remove_fields"
and here is my error:
NoMethodError in Contracts#new
Showing /home/tom/rails_projects/tracking/app/views/contracts
/_codeline_fields.html.haml where line #9 raised:
undefined method `count' for :units_alloc:Symbol
if I use units_alloc in the argument instead of the symbol, I still get an error:
NameError in Contracts#new
Showing /home/tom/rails_projects/tracking/app/views/contracts
/_codeline_fields.html.haml where line #9 raised:
undefined local variable or method `units_alloc' for
#<#<Class:0xadbde90>:0xa8956e8>
I tried to use 'codeline.units_alloc' but this did not work and the same error was flagged.
Any suggestions, or pointers to help me resolve this issue?
Thanks.
Solution: Thanks to James Scott Jr.
app/controller/contracts_controller.rb
def New
#show_remove = false
....
....
end
app/views/contracts/_codelines_fields.html.haml
.field
= codeline.label :name, "Units Alloc"
%br/
= codeline.text_field :units_alloc, :precision => 6, :scale => 2, :size => 10,
:class => "ui-state-default"
- if #show_remove
= codeline.hidden_field :_destroy
= link_to "remove", '#', class: "remove_fields"
- else
- #show_remove = true
And that did it ... the remove button only shows in the second and subsequent row of attributes.
By the time you're in the form (partial), codeline doesn't refer to an instance the instance of Codeline that the form (partial) is for, but an instance of an ActionView::Helpers::FormBuilder that simple knows how to associate information the the instance of Codeline. You knew that because in the first line of the partial, you have codeline.object.build_code.
So, if you want to access the information about the units_alloc associated, you would access them with codeline.object.units_alloc. That will give you your data for your conditional.
I would just like to add that if the purpose of your anchor tag is to remove elements from a form list using some javacscript, you might be using the wrong control for it. Anchor tags are not form elements, they should point to resources/content and are not there to be used as animation/client side behaviour triggers. According to the use case you describe, an input tag type=button would be a much more appropriated element for what you seem to be trying to achieve.