Rspec no Method error assignment - ruby-on-rails-3

I apparently added a new field to my Customer model known as ct_ratio before running tests. When I now run tests on my invoice spec, they fail with a "No method error,ct_ratio="
Customer.rb
class Customer < ActiveRecord::Base
attr_accessible :billing_address, :customer_currency, :email, :first_name, :last_name, :mobile, :name, :payment_terms, :phase_type, :readings_attributes, :pays_vat, :ct_ratio
before_validation do
self.ct_ratio ||= 1
end
end
Invoice_spec
describe Invoice do
context 'create_item_from_readings' do
before :each do
#customer = FactoryGirl.create :customer
#reading1 = #customer.readings.create! reading1: 100, date_of_reading: 30.days.ago
#reading2 = #customer.readings.create! reading1: 200, date_of_reading: 20.days.ago
#reading3 = #customer.readings.create! reading1: 500, date_of_reading: 10.days.ago
#customer.stub(:unit_cost).and_return(100)
end
it "should create an invoice item for all reading" do
invoice = Invoice.new customer: #customer, invoice_date: 15.days.ago, due_date: Date.today
item = invoice.create_item_from_readings
item.rate.should == 100
item.amount.should == 100 * 100
item.description.should == "Electricity used from #{#reading1.date_of_reading.strftime('%d/%m/%Y')} to #{#reading2.date_of_reading.strftime('%d/%m/%Y')} - 100 units"
end
I added ct_ratio to Factory Girl
require 'factory_girl'
FactoryGirl.define do
factory :customer do
name 'Test Test'
first_name "Test"
last_name "Test"
mobile "00000000"
billing_address "Kampala"
payment_terms "Immediate"
phase_type "Single Phase"
customer_currency "UGX"
pays_vat false
email "test#test.com"
ct_ratio 1
end
factory :reading do |f|
f.reading1 100
f.reading2 150
f.reading3 200
f.date_of_reading 30.days.ago
end
end

this is a common error when not running tests via rake and your migration is not run on the test-database.
run RAILS_ENV=test rake db:migrate first and check out your testsuite.

Related

after_build runs 2 times in FactoryGirl

There is my model:
class Profile < ActiveRecord::Base
after_create do
pp id
track_activity
end
end
This is my factoty:
factory :user do
email {Factory.next :email}
after_build do |user|
user.profile_attributes = {name: 'why'}
end
end
The id prints 2 times with the follow code in spec:
expect do
user = create :user
end.to change(Activity, :count).by 1

Rails saving data from associated form

How can I get the data from an associated form and insert it to the associated table from the main model?
class Supplier < ActiveRecord::Base
has_one :account, foreign_key: "acc_sup_id", :autosave => true
self.primary_key = 'sup_id'
end
class Account < ActiveRecord::Base
belongs_to :supplier, foreign_key: "acc_sup_id"
self.primary_key = 'acc_id'
self.table_name = 'accounts'
end
I am having a combined form for Supplier and Account. When I submit I need to find a way to insert the corresponding values to Supplier and Account. The problem is Supplier values is inserting properly but not Account.
I have asked the same question in several forums, groups and even in stack but nobody seems to give a convincing answer.
The basic strategy is to first look at what params are being submitted when the form is submitted. You could add a line in the controller action such as raise params.inspect to see that. Make sure that those paras contain all the data you need; if not then there is some problem in the view that generates that form.
Once you have all the data getting to the controller action, then you need to change the controller action so that is properly interprets all the data and puts it into the correct models.
I cannot give any more specific advice unless you show the code for your view, the result from doing params.inspect, and the code for the controller action that takes the data.
Try this.
Let's assume that there are orders and customers tables and that you want to perform CRUD operations on customers from orders form.
Customer model is very simple
class Customer < ActiveRecord::Base
attr_accessible :name
end
Order model must provide virtual attributes for all customer's attributes (attr_accessor construct). CRUD for customers is provided through callbacks. Validations can be used as well.
class Order < ActiveRecord::Base
attr_accessor :customer_name
attr_accessible :description, :number, :customer_name
belongs_to :customer
validates_presence_of :number
validates_presence_of :description
validates_presence_of :customer_name
before_save :save_customer
after_find :find_customer
after_destroy :destroy_customer
protected
def save_customer
if self.customer
self.customer.name = self.customer_name
else
self.customer = Customer.create(name: self.customer_name)
end
self.customer.save
end
def find_customer
self.customer_name = self.customer.name
end
def destroy_customer
self.customer.destroy
end
end
Example grid for Order model.
class Orders < Netzke::Basepack::Grid
def configure(c)
super
c.model = 'Order'
c.items = [
:description,
:number,
:customer_name
]
c.enable_edit_inline = false
c.enable_add_inline = false
end
def preconfigure_record_window(c)
super
c.form_config.klass = OrderForm
end
end
Example form for Order model.
class OrderForm< Netzke::Basepack::Form
def configure(c)
super
c.model = 'Order'
c.items = [
:description,
:number,
:customer_name
]
end
end

how can i use Capybara without tests

in my Rails app in DB i have some query.
# PostController
#post.query # => 'blabla'
and i want put this string in google or yahoo
in simple ruby file i use
require ... all gems
Capybara.app_host = 'http://www.google.com/'
and
class Google
include Capybara::DSL
def search
visit('/')
fill_in "q", :with => "blah blah"
click_button("Google")
...
but how can I put this code in controller (or model method)?
Capybara is not intended for such use. You might want to try mechanize instead.
class PostsController < ApplicationController
require 'capybara'
require 'capybara/dsl'
include Capybara::DSL
Capybara.current_driver = :webkit
def index
#posts = Post.all
end
def show
#post = Post.find(params[:id])
visit(#post.search_type)
fill_in "q", :with => #post.query
click_button("Google")
loop_variable = 0
num_of_page = 1
max_count_of_page = 4
flag_on_break = false
while(loop_variable == 0) do
has_on_page = page.has_content?(#post.search_question)
if has_on_page
loop_variable = 1
else
find('.b:last a').click
num_of_page += 1
end
if num_of_page > max_count_of_page
flag_on_break = true
break
end
end
if flag_on_break
#number = 'Nothing not found'
else
#number = num_of_page
end
end
def new
#post = Post.new
end
def create
#post = Post.new(params[:post])
if #post.save
flash[:notice] = "Post created!"
redirect_to root_path
end
end
end
this is a piece of my code - but the main idea, I think, is understandable

Access parent of has_many relationship

Is there a way to access the parent of a polymorphic model in Mongoid 3?
I have this relationship
class Project
...
field "comments_count", :type => Integer, :default => 0
has_many :comments, :as => :commentable
...
end
class Comment
...
field "status"
belongs_to :commentable, :polymorphic => true
before_validation :init_status, :on => :create
after_create :increase_count
def inactivate
self.status = "inactive"
decrease_count
end
private
def init_status
self.status = 'active'
end
def increase_count()
#commentable.inc(:comments_count, 1)
end
def decrease_count()
#commentable.inc(:comments_count, -1)
end
...
end
I'd like to be able to update the comments_count in the parent relationship when the comment is inactivated since doing a count() on the child is very expensive (and I'd need to do that a lot in the app). I have the increase_count working, but I can't access #commentable in decrease_count (#commentable = nil). Any ideas?
The # in #commentable is unnecessary because its not an instance variable of your model. So:
def increase_count()
commentable.inc(:comments_count, 1)
end
def decrease_count()
commentable.inc(:comments_count, -1)
end
should do the trick.

How can I map between strings and attributes automatically?

I have a tiny logical error in my code somewhere and I can't figure out exactly what the problem is. Let's start from the beginning. I have the following extension that my order class uses.
class ActiveRecord::Base
def self.has_statuses(*status_names)
validates :status,
:presence => true,
:inclusion => { :in => status_names}
status_names.each do |status_name|
scope "all_#{status_name}", where(status: status_name)
end
status_names.each do |status_name|
define_method "#{status_name}?" do
status == status_name
end
end
end
end
This works great for the queries and initial setting of "statuses".
require "#{Rails.root}/lib/active_record_extensions"
class Order < ActiveRecord::Base
has_statuses :created, :in_progress, :approved, :rejected, :shipped
after_initialize :init
attr_accessible :store_id, :user_id, :order_reference, :sales_person
private
def init
if new_record?
self.status = :created
end
end
end
Now I set a status initially and that works great. No problems at all and I can save my new order as expected. Updating the order on the other hand is not working. I get a message saying:
"Status is not included in the list"
When I check it seems that order.status == 'created' and it's trying to match against :created. I tried setting the has_statuses 'created', 'in_progress' etc but couldn't get some of the other things to work.
Anyway to automatically map between string/attribute?
from your description, looks like you're comparing a string to a symbol. Probably need to add:
define_method "#{status_name}=" do
self.status = status_name.to_sym
end
or do a #to_s on the status_names