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.
Related
I recently upgraded my app from Rails 3 to Rails 4, and I'm trying to run the specification tests. Code that I presume used to work just fine (before my time here) suddenly throws an error.
The error:
1) Admin::ReviewsController while logged in #index should get index
Failure/Error: stub_search("product")
ArgumentError:
wrong number of arguments (1 for 2+)
# ./spec/support/searchkick_stub.rb:5:in `stub_search'
# ./spec/controllers/admin/reviews_controller_spec.rb:8:in `block (3 levels) in <top (required)>'
Here is the searchkick_stub.rb:
module SearchkickStub
def stub_search(model)
klass = model.to_s.camelize.constantize
klass.any_instance.stub(:reindex) { true }
klass.stub(:search) do |term, options|
options ||= {}
#search_term ||= term
#search_params ||= options.dup
response = {
'hits' => {
'total' => 0,
'hits' => [],
}
}
result_opts = {
# per Searchkick::Query.new
page: [options[:page].to_i, 1].max,
per_page: (options[:limit] || options[:per_page] || 100000).to_i,
padding: [options[:padding].to_i, 0].max,
load: options[:load].nil? ? true : options[:load],
# per Searchkick::Query.execute
includes: options[:include] || options[:includes],
json: !options[:json].nil?,
}
Searchkick::Results.new(klass, response, result_opts)
end
# Code that reindexes Products will reindex their Inventories too.
stub_search(:inventory) if model == :product
end
end
The signature of stub_search is clearly for a single argument, not two or more like the error claims.
And here is where we use stub_search in reviews_controller_spec.rb
describe ReviewsController do
include SearchkickStub
before do
stub_search(:product)
...
end
end
Figured it out. Per https://github.com/rspec/rspec-rails/issues/941, the issue was the line: require 'minitest/autorun' in spec_helper.rb. This line was added to remove the followig warnings:
Warning: you should require 'minitest/autorun' instead.
Warning: or add 'gem "minitest"' before 'require "minitest/autorun"'
But it turns out that all you need is gem "minitest" in the Gemfile (even though it was already installed, as a dependency for something else, and appeared in Gemfile.lock).
I think the issue comes more from the ruby upgrade. There may have been changes to the interpreter around how block arguments were handled. The search method is stubbed to take 2 arguments in your code: term and options. But it's only invoked with one argument: "product".
options is set to a default value on the first line in that block with options ||= {} so not passing options may not have been a problem with 1.9.3, but with stricter argument checks it breaks in 2.1.5.
A simple fix is to set a default argument in the block arguments, eg.
klass.stub(:search) do |term, options|
to
klass.stub(:search) do |term, options={}|
You can also safely remove the options ||= {} line after doing this.
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 using a t.text :emails, array: true, default: [], null:false in my rails 4 migration for emails in the a reporter. There I'm validating each entry with the following code
validates_each :emails do |record, attr, value|
value.each do |email|
record.errors.add attr, I18n.t('reporter.error.not_valid_email', email: email) if (email =~ EMAIL_VALIDATION_REGEXP) == nil
end
end
And I'm getting the following error when I'm creating a instance of the AM class
1) Reporter budget, receipt and member interaction testing the remaining_promise_for_whole_budget_title method for overview of all available budgets
Failure/Error: #reporter = FactoryGirl.create(:reporter)
NoMethodError:
undefined method `each' for "[\"lkajsdf#gmail.com\"]":String
# ./app/models/reporter.rb:6:in `block in <class:Reporter>'
# /Users/malik/.rvm/gems/ruby-2.2.1#maalify/gems/activemodel-4.2.0/lib/active_model/validator.rb:179:in `call'
Here is my factory girl definition
FactoryGirl.define do
factory :reporter do
name "MyReport"
donations %W(1 2)
tanzeems "MyString"
interval "28"
emails ["lkajsdf#gmail.com"]
end
end
FactoryGirl.define do
factory :reporter do
name "MyReport"
donations %W(1 2)
tanzeems "MyString"
interval "28"
emails { ["lkajsdf#gmail.com"] }
end
end
Here's the solution. Let it be in the block.
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'
Im pretty new to ruby on rails.
I just finished this tutorial and i am trying to make my own ruby website from scratch
As soon as i switched my sin-tax to the less verbose one i am getting errors:
the errors I get are:
1) Pages Home page
Failure/Error: it { should have_content('Home') }
NoMethodError:
undefined method `has_content?' for "Home page":String
# ./spec/requests/pages_spec.rb:7:in `block (3 levels) in <top (required)>'
2) Pages Home page
Failure/Error: it { should have_title('Home') }
NoMethodError:
undefined method has_title?' for "Home page":String
# ./spec/requests/pages_spec.rb:8:inblock (3 levels) in '
this is my rspec file
require 'spec_helper'
describe "Pages" do
describe "Home page" do
before { visit root_path }
it { should have_content('Home') }
it { should have_title('Home') }
end
end
I have no idea what is going on did i forget to include something in my gemfile?
If you want any more info comment and ill include it here
Try
it 'has home title' do
expect(page).to have_title('Home')
end
it 'has home content' do
expect(page).to have_content('Home')
end
Or
subject { page }
it { should have_title('Home') }
it { should have_content('Home') }