React class=container matters ... needs to surround all components. having components declared outside and the page will not render
Saturday, June 6, 2015
Cliff Notes for React.js Component State
- Mutate State only using the provided methods. (e.g. setState())
- In the render method retrieve properties with "this.state.varname"
https://facebook.github.io/react/docs/component-api.html
To ponder further:
"Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use
And data flow is well described here:
https://github.com/facebook/flux
- Refs to include any child components as "state"
- Warned "By default, use the Reactive data flow and save
refs for use cases that are inherently non-reactive"
To ponder further:
"Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use
refs to "make things happen" – instead, the data flow will usually accomplish your goal."And data flow is well described here:
https://github.com/facebook/flux
Saturday, October 18, 2014
Further Experiments with grunt-init
The examples on https://github.com/r3b/ConnectJS2014 walk through an iterative build up of tools node --> npm --> grunt --> express
Key tool seems to be the grunt-init task which works like an archetype builder, using a template it sets up a standard of config files for various steps
- package.json : for all module dependencies
- Gruntfile.js : build, test, deploy tasks.
Get new templates by cloning the Git repository to your ~/.grunt-init directory.
Command to instantiate the new archetype should be run inside an empty directory, followed by npm to download dependencies, and lastly grunt to execute default tasks.
>grunt-init {templatename}
> npm install
> grunt
Have learned since then:
> grunt -h
lists all available tasks with handy descriptions, so easy to find out what a template does.
Curious to see how best to handle grunt-init "mashups" and combining of templates. Since grunt-init is for empty directories only, seems like you still need to then iterate by hand as your project grows... or install a bunch of fluff at first for when you think you will need it later.
And have tried a couple of grunt + express templates... none of which seem to just "run" off the bat...
Monday, September 15, 2014
Fun with JS scope and closure : Sep 15 ATL.JS Chris Aquino
Inspired from tonights ATL.JS talk
Closure and the for loop problem: If you really like 10
for(i=0; i < 10; i++){
setTimeout( function(){
console.log("i is " + i);}, 10);
}
Javascript is A) Lazy and B) Single Threaded. So.... contrary to what you want: For loop executes in the thread, AND then the i inside the closure function executes and sees that i now = 10 (last value).
Scope is a matter of perspective: if you prefer undefined instead of 10
for(i=0; i < 10; i++){
setTimeout( function(i){
console.log("i is " + i);}, 10);
}
So now, i is an argument, and it's not assigned when the function is created. It stays undefined.
And even explicit assignment doesn't help. The y here is part of the for loop, so gets assigned 9 times, then function executes:
for(i=0; i < 10; i++){
var y = i;
setTimeout( function(){
console.log("i is " + y);}, 10);
}
So for readable, manageable scope: create a function to create the function, so that each execution of the loop the iterator value is captured to a isolated scope and preserved until later.
function showI(i){
function show() {
console.log("i is "+ i);
};
return show;
}
for(i=0; i < 10; i++){
setTimeout( showI(i), 10);
}
Closure and the for loop problem: If you really like 10
for(i=0; i < 10; i++){
setTimeout( function(){
console.log("i is " + i);}, 10);
}
Javascript is A) Lazy and B) Single Threaded. So.... contrary to what you want: For loop executes in the thread, AND then the i inside the closure function executes and sees that i now = 10 (last value).
Scope is a matter of perspective: if you prefer undefined instead of 10
for(i=0; i < 10; i++){
setTimeout( function(i){
console.log("i is " + i);}, 10);
}
So now, i is an argument, and it's not assigned when the function is created. It stays undefined.
And even explicit assignment doesn't help. The y here is part of the for loop, so gets assigned 9 times, then function executes:
for(i=0; i < 10; i++){
var y = i;
setTimeout( function(){
console.log("i is " + y);}, 10);
}
So for readable, manageable scope: create a function to create the function, so that each execution of the loop the iterator value is captured to a isolated scope and preserved until later.
function showI(i){
function show() {
console.log("i is "+ i);
};
return show;
}
for(i=0; i < 10; i++){
setTimeout( showI(i), 10);
}
Thursday, July 4, 2013
AngularJS - Scope Kata
Scope is where a good part of Angularjs magic happens, binding allows data to be updated by events on the DOM and for changes of data to be reflected by data in the DOM. Scope is more than just a handle for a bunch of variables and it can behave unexpectedly until you understand what's going on behind the scenes
"Scope is not the model.. it is just a reference to what's happening [inside the dom]" egghead.io tutorial
- Root scope sits at the top of the scope inheritance, changes to this model
can be reflected across all other application scopes which are children of the root scope. - Root scope is accesible without direct reference
- Controller scopes are children of root scope, and variables not found local will be pulled from parent scopes all the way back to root.
- If you declare 2 of the same controller on a view, they are siblings and each has it's own scope, so variables are not shared between them
Plain Variables
Plain variables lose inheritance as soon as written in child scopes. They are local to the current scope only after that.Model Variable
Model variables are declared as properties of an object "model.variable". These will maintain inheritance from parent to child scopes, as unlike plain variables, each child is pulling the model reference from parent and only changing the property on the shared object.
Of course if Controllers are siblings, the scopes are not shared regardless if you use plain variables or model notation variables.
Friday, January 4, 2013
Java, Groovy, Android and the URL with underscore problem
lesson for today:
Groovy HTTPBuilder chokes on URLs where the hostname contains and underscore character. For example http://xx_host.name.domain.com. Apparently the blame lies with the underlying java URL class which fails to parse due to the "illegal" underscore character.
What I find weird is how quietly folks seem to be accepting this limitation. Affects android as well. Yes, strictly speaking underscores are not valid hostname characters, but apparently that rule has been relaxed for subdomains and DNS configurations? Either way from the various posts I've seen looks like underscores are here to stay and problems have been encountered with facebook, amazon aws and other big names.
If there's a workaround out there other than injecting the IP address instead of hostname would love to hear about it. I really, really hate it when my code is tied to a strict IP address.
Groovy HTTPBuilder chokes on URLs where the hostname contains and underscore character. For example http://xx_host.name.domain.com. Apparently the blame lies with the underlying java URL class which fails to parse due to the "illegal" underscore character.
What I find weird is how quietly folks seem to be accepting this limitation. Affects android as well. Yes, strictly speaking underscores are not valid hostname characters, but apparently that rule has been relaxed for subdomains and DNS configurations? Either way from the various posts I've seen looks like underscores are here to stay and problems have been encountered with facebook, amazon aws and other big names.
If there's a workaround out there other than injecting the IP address instead of hostname would love to hear about it. I really, really hate it when my code is tied to a strict IP address.
Friday, April 8, 2011
Rails - Record Handling Tricks learned the hard way
- use dynamic model query methods described in: http://api.rubyonrails.org/classes/ActiveRecord/Base.html
- Story.order("column_ord").find_all_by_state("B").size returns the collection
- Story.order("column_ord").find_by_state("B").size returns only one story
- render(@collection) throws error if said collection is empty, so check <% if @collection then render(@collection) end %>
- assigns[:variablename] is how to get hold of a page object in the controller_test
- Story.order("column_ord").find_all_by_state("B").size returns the collection
- Story.order("column_ord").find_by_state("B").size returns only one story
- render(@collection) throws error if said collection is empty, so check <% if @collection then render(@collection) end %>
- assigns[:variablename] is how to get hold of a page object in the controller_test
Ruby: Stringception - a string within a string
good reference on all the various ways to define strings in ruby
http://www.techotopia.com/index.php/Ruby_Strings_-_Creation_and_Basics
So that you can run testing like:
assert_difference( %[Story.count :conditions => 'state = "P"']) do
put :drop, :id => story.to_param, :state => 'P'
end
Where the query string contains a string.
http://www.techotopia.com/index.php/Ruby_Strings_-_Creation_and_Basics
So that you can run testing like:
assert_difference( %[Story.count :conditions => 'state = "P"']) do
put :drop, :id => story.to_param, :state => 'P'
end
Where the query string contains a string.
Thursday, April 7, 2011
jquery w/ rails : ajax update of drag & drop item
A script added to my html.erb file, at page load it establishes sortable columns, and ajax call to automatically update an item when it is dragged from one column to another:
The drop_url references as routes.rb entry /board/drop to a specific board_controller method. Upon retrospect, I'm thinking this ought to work with the default update method on my :story resource. Note to self, if your update method doesn't update... check that you haven't forgotten your parameter naming conventions. status != state no matter how you write the method to update.
$(function() {
$(".sortcol").sortable({
connectWith: ".sortcol",
receive: function(event, ui) {
$.ajax({
url: "<%= drop_url() %>",
type: 'PUT',
data: $.param({id : ui.item.attr('id'), state : ui.item.parent().attr('id')}),
success: function(d) { ui.item.effect("pulsate", {} , 500 ) }
})//end get
} //end receive function
}); //end sortable
}); // end function
The drop_url references as routes.rb entry /board/drop to a specific board_controller method. Upon retrospect, I'm thinking this ought to work with the default update method on my :story resource. Note to self, if your update method doesn't update... check that you haven't forgotten your parameter naming conventions. status != state no matter how you write the method to update.
Saturday, April 2, 2011
Rails -migrations with column default changes
So wanted to add a default value for a column, but also wanted to do a proper rollback method on the migration. My problem may have been more with SQLite than rails, something about it not liking alter column commands.
Anyway:
change_column :table, :column, :type, default = 'value' did update the schema.
But also needed to add the date
Table.update_all( "column = 'value'", "column IS NULL") to fix unset values.
Didn't find a good syntax to remove the default setting from the schema.
Anyway:
change_column :table, :column, :type, default = 'value' did update the schema.
But also needed to add the date
Table.update_all( "column = 'value'", "column IS NULL") to fix unset values.
Didn't find a good syntax to remove the default setting from the schema.
Saturday, March 12, 2011
Rails - Ruby: lesson in MVC
So turns out if you apply MVC correctly you save yourself from lots of unnecessary objects!
Originally I thought I needed a Board --> Panel --> Story. But as mentioned last post, using poro instead of ActiveRecord was getting 'interesting', as I had decided I didn't need any state for Board and Panel. As I was fixing tests... suddenly realized how all this was very unnecessary work:
The better solution is to create a BoardController, and then define the panels as simple attributes of that controller that reference the appropriate collection of stories:
class BoardController < ApplicationController
def show
@backlog = Story.find :all, :conditions => 'state IS NULL'
respond_to do |format|
  format.html # show.html.erb
  format.xml { render :xml => @stories }
end
end
end
Now instead of needing to keep a bunch of keys, names in alignment between the view, board, panel objects... I just have simple associations. Each named collection I want is an attribute in the board controller, available to the view. The view simply needs to render each attribute appropriately. This approach also seem to have simplified my views, since now I just have the 'board' view, and a '_story' partial view to render each collection element.
Originally I thought I needed a Board --> Panel --> Story. But as mentioned last post, using poro instead of ActiveRecord was getting 'interesting', as I had decided I didn't need any state for Board and Panel. As I was fixing tests... suddenly realized how all this was very unnecessary work:
The better solution is to create a BoardController, and then define the panels as simple attributes of that controller that reference the appropriate collection of stories:
class BoardController < ApplicationController
def show
@backlog = Story.find :all, :conditions => 'state IS NULL'
respond_to do |format|
  format.html # show.html.erb
  format.xml { render :xml => @stories }
end
end
end
Now instead of needing to keep a bunch of keys, names in alignment between the view, board, panel objects... I just have simple associations. Each named collection I want is an attribute in the board controller, available to the view. The view simply needs to render each attribute appropriately. This approach also seem to have simplified my views, since now I just have the 'board' view, and a '_story' partial view to render each collection element.
Ruby-Rails : lessons on rails ActiveRecord vs plain old rails objects
Got distracted from doing the Agile-Web-Development-With-Rails examples, am now starting from scratch on an experiment with jquery and rails. I'm looking to see what I can achieve from a robust client app with rails based data & services via ajax.
1) Unit Tests throwing " ActiveRecord::StatementInvalid: Could not find table 'panels' "
Kept seeing this error for several basic assert statements in the model unit tests.
> assert p.is_a(Panel)
> assert p.display_text == 'backlog'
Noob mistake here... using 'rails g model' for objects that will not be stored in the database. Caused the objects to inherit from ActiveRecord class, and when ActiveRecord triggers automagic that expects a table to exist for the Panel class, and complains when it doesn't.
Instead, I really wanted to be dealing with plain old ruby objects, and viola! once I deleted the ActiveRecord reference in the model object.
> couldn't use is_a, instead had to use ruby method is_a?
> have to define the accessor methods for private instance variables.
1) Unit Tests throwing " ActiveRecord::StatementInvalid: Could not find table 'panels' "
Kept seeing this error for several basic assert statements in the model unit tests.
> assert p.is_a(Panel)
> assert p.display_text == 'backlog'
Noob mistake here... using 'rails g model' for objects that will not be stored in the database. Caused the objects to inherit from ActiveRecord class, and when ActiveRecord triggers automagic that expects a table to exist for the Panel class, and complains when it doesn't.
Instead, I really wanted to be dealing with plain old ruby objects, and viola! once I deleted the ActiveRecord reference in the model object.
> couldn't use is_a, instead had to use ruby method is_a?
> have to define the accessor methods for private instance variables.
Monday, February 7, 2011
Rails - Task I: Logging In - Noob notes on authlogic
There's a little auto-magic going on that as a rails/ruby noob I didn't expect.
1) The password, password_confirmation fields are not explicitly declared anywhere except for your registration, login views. This mean you have to add the "acts_as_authentic" to your User class BEFORE you can being using these fields in your views and tests.
2) Naming of your DB fields is important, password_confirmation != confirm_password. (Coming from a Java background, this feels weird, not having name control over model fields. Just go with it.)
3) After you do add acts_as_authentic, you have to update user_controller_test. Passing user.parameters doesn't work anymore, since that's the DB model and not what the user will send -- example of the changes that worked for me.
4) Really enjoying the automated testing, they have been catching all kinds of mistakes I make in ignorance, and a great teaching tool. Am beginning to see how much you can skip explicit tutorials and APIs if the testing is robust.
1) The password, password_confirmation fields are not explicitly declared anywhere except for your registration, login views. This mean you have to add the "acts_as_authentic" to your User class BEFORE you can being using these fields in your views and tests.
2) Naming of your DB fields is important, password_confirmation != confirm_password. (Coming from a Java background, this feels weird, not having name control over model fields. Just go with it.)
3) After you do add acts_as_authentic, you have to update user_controller_test. Passing user.parameters doesn't work anymore, since that's the DB model and not what the user will send -- example of the changes that worked for me.
test "should create user" do
assert_difference('User.count') do
post :create, :user => {:email => 'test@functional.com', :password => 'godpassword', :password_confirmation => 'godpassword'}
end
4) Really enjoying the automated testing, they have been catching all kinds of mistakes I make in ignorance, and a great teaching tool. Am beginning to see how much you can skip explicit tutorials and APIs if the testing is robust.
Sunday, February 6, 2011
Rails - Task I: Logging In w/ authlogic_example
Picking up on a new branch, and take a few integration shortcuts to get authlogic up and running.
> git pull git://github.com/trevmex/authlogic_rails3_example
Then working through the merges necessary to merge in authlogic code, with a few skips
* git checkout --ours db/schema.rb
* git checkout --ours db/seeds.rb
* git checkout --theirs Gemfile
* change config/initializers/rspec_generator.rb Replace AuthlogicRails3Example with Depot (or your app name)
Then after code looked reasonably merged
> bundle install
> rake
Get complaints about unknown email_format validator
Seemed to have missed an important set of entries in config/application.rb
This is required to reference the format validator introduced with the AuthLogic Example.
After this fix we get to something interesting... the rspec tests fail!
> git pull git://github.com/trevmex/authlogic_rails3_example
Then working through the merges necessary to merge in authlogic code, with a few skips
* git checkout --ours db/schema.rb
* git checkout --ours db/seeds.rb
* git checkout --theirs Gemfile
* change config/initializers/rspec_generator.rb Replace AuthlogicRails3Example with Depot (or your app name)
Then after code looked reasonably merged
> bundle install
> rake
Get complaints about unknown email_format validator
Seemed to have missed an important set of entries in config/application.rb
#Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += %W(#{config.root}/lib/**/)
This is required to reference the format validator introduced with the AuthLogic Example.
After this fix we get to something interesting... the rspec tests fail!
Rails - Task I: Logging In
For this task I decided to diverge from the book. From what I've heard attending Atlanta's local chapter meetings for OWASP (www.owasp.org), own-rolled authentication is at the root of far too many security flaws and breeches in web applications. Granted this book touches on some of the oft overlooked necessities (e.g. salted hash passwords), but for a real live website, I always push to use a robust, tested, peer-reviewed plugin over hand rolled code. At the very least, typical project timelines leave little time for developers and testers to stay current on the ever evolving threat landscape. If your shop is different, please, please help out the rest of us.
I looked around a bit and decided to go with authlogic. Trevmex has provided a fully Rails3 ready example found at https://github.com/trevmex/authlogic_rails3_example . http://www.dixis.com/?p=352 rewrites the tutorial for a few other steps you need to then incorporate the module into the depot code. (I did start first trying more commonly referenced authlogic_example by binarylogic at https://github.com/binarylogic/authlogic_example, but all I succeeded at was proving what I complete noob I am)
What follows is a combination of various sources. Comments indicate what prompted each step to be taken, but not the rationale or theory behind it.
Pre-Iteration Work: Adding authlogic to depot
$ sudo gem install authlogic #binarylogic
To depot Gemfile add:
# Add support for Authlogic authentication
gem 'authlogic', :git => 'git://github.com/odorcicd/authlogic.git', :branch => 'rails3' #trevmex
gem "rails3-generators" #dixis
> bundle install #'cause rake prompted me to run this after the changes.
> rails generate authlogic:session UserSession #dixis
>rake test
And viola! everything now fails because of 'ActiveRecord::StatementInvalid: SQLite3::SQLException: no such table: user_sessions: DELETE FROM "user_sessions" WHERE 1=1'
bummer!
I looked around a bit and decided to go with authlogic. Trevmex has provided a fully Rails3 ready example found at https://github.com/trevmex/authlogic_rails3_example . http://www.dixis.com/?p=352 rewrites the tutorial for a few other steps you need to then incorporate the module into the depot code. (I did start first trying more commonly referenced authlogic_example by binarylogic at https://github.com/binarylogic/authlogic_example, but all I succeeded at was proving what I complete noob I am)
What follows is a combination of various sources. Comments indicate what prompted each step to be taken, but not the rationale or theory behind it.
Pre-Iteration Work: Adding authlogic to depot
$ sudo gem install authlogic #binarylogic
To depot Gemfile add:
# Add support for Authlogic authentication
gem 'authlogic', :git => 'git://github.com/odorcicd/authlogic.git', :branch => 'rails3' #trevmex
gem "rails3-generators" #dixis
> bundle install #'cause rake prompted me to run this after the changes.
> rails generate authlogic:session UserSession #dixis
>rake test
And viola! everything now fails because of 'ActiveRecord::StatementInvalid: SQLite3::SQLException: no such table: user_sessions: DELETE FROM "user_sessions" WHERE 1=1'
bummer!
Saturday, January 22, 2011
Grails with Aptana Studio 3 on Mac OSX
Setting JAVA_HOME: (http://www.oreillynet.com/mac/blog/2001/04/mac_os_x_java_wheres_my_java_h.html )
setenv JAVA_HOME /System/Library/Frameworks/JavaVM.framework/Home
Setup Grails (http://www.grails.org/Installation)
git clone git://github.com/grails/grails-core.git
Set the GRAILS_HOME environment variable to CHECKOUT_LOCATION/grails-core
Add the $GRAILS_HOME\bin directory to your PATH environment variable
Go to the GRAILS_HOME directory and run: ./gradlew libs
In Aptana Studio Workspace
grails create-app grails-demo
New Project 'grails-demo'
Then in the grails-demo project
> grails run-app
Note that grails commands feel much slower than the equivalent ruby commands, and initial application startup is significantly slower. I actually was beginning to wonder if everything was working as the browser spun.. patience paid off and I was rewarded with the initial welcome page.
Also attempted to add some sort of groovy support, but without any real success. Java editor helps with syntax highlighting of terms in the groovy files, but is cluttered reporting other syntax and compile errors 'cause doesn't understand groovy.
Note that 'natures' do report several groovy natures, but these do not appear to be associated with any file types.
setenv JAVA_HOME /System/Library/Frameworks/JavaVM.framework/Home
Setup Grails (http://www.grails.org/Installation)
git clone git://github.com/grails/grails-core.git
Set the GRAILS_HOME environment variable to CHECKOUT_LOCATION/grails-core
Add the $GRAILS_HOME\bin directory to your PATH environment variable
Go to the GRAILS_HOME directory and run: ./gradlew libs
In Aptana Studio Workspace
grails create-app grails-demo
New Project 'grails-demo'
Then in the grails-demo project
> grails run-app
Note that grails commands feel much slower than the equivalent ruby commands, and initial application startup is significantly slower. I actually was beginning to wonder if everything was working as the browser spun.. patience paid off and I was rewarded with the initial welcome page.
Also attempted to add some sort of groovy support, but without any real success. Java editor helps with syntax highlighting of terms in the groovy files, but is cluttered reporting other syntax and compile errors 'cause doesn't understand groovy.
Note that 'natures' do report several groovy natures, but these do not appear to be associated with any file types.
Saturday, January 15, 2011
Rails - Iteration E3 -Fixture tests for prices
Need further study: http://api.rubyonrails.org/classes/Fixtures.html
When I tried to follow simple example e.g.
one_quantity_two:
product_id: one
cart_id: 2
quantity: 2
line_item.product was a nil object.
The format that did work
one_quantity_two:
product_id: <%= Fixtures.identify(:one) %>
cart_id: 2
quantity: 2
Most likely culprit --> rails/ruby version?
When I tried to follow simple example e.g.
one_quantity_two:
product_id: one
cart_id: 2
quantity: 2
line_item.product was a nil object.
The format that did work
one_quantity_two:
product_id: <%= Fixtures.identify(:one) %>
cart_id: 2
quantity: 2
Most likely culprit --> rails/ruby version?
Iteration E2: Functional Test for bad cart
test "should redirect on invalid cart" do
get :show, :id => 'wibble'
assert_redirected_to store_path
assert_match flash[:notice], "Invalid cart"
end
TBD: use internationalized error message?
get :show, :id => 'wibble'
assert_redirected_to store_path
assert_match flash[:notice], "Invalid cart"
end
TBD: use internationalized error message?
FYI - cause of the critical bug?
bad --> @line_item = @cart.add_product(:product.id)
good --> @line_item = @cart.add_product(product.id)
First case not passing id, instead passing (I think) an object reference! gotta love those one character typos!
good --> @line_item = @cart.add_product(product.id)
First case not passing id, instead passing (I think) an object reference! gotta love those one character typos!
Rails - Iteration E1 - line_item aggregation starts new
Take 2 on smarter cart!
First: add a unit test for the cart.add_product method
test "cart aggregates line items" do
c = carts(:one)
assert_equal 0, c.line_items.count, "cart items not empty at start of test"
p = products(:ruby)
item = c.add_product(p.id)
assert_equal 1, c.line_items.count, "first product add did not create new line item"
assert_equal 1, item.quantity, "new item quantity not 1"
item = c.add_product(p.id) #hold reference for future testing
assert_equal 1, c.line_items.count, "readd product caused increase in line items count"
assert_equal products(:ruby).id, item.product.id, "a problem with product id between line item and orig"
end
(Note to self: originally tried to do above like:
- assert_difference('c.line_items.count') do
- p = products(:ruby)
- c.add_product(p.id)
- c.save
- end
Note that the assert_difference requires a DB save event. Decided I didn't like that extra dependency on a unit test. Also note that the assert_difference requires a string not an object expression.)
Second: modify line_item_controller test to show aggregation of line items
test "should create/update line_item" do
#original test when just creating new items (iteration D)
assert_difference('LineItem.count') do
post :create, :product_id => products(:ruby).id
end
assert_redirected_to cart_path(assigns(:line_item).cart)
#new test - just repeat old and this time no_difference
assert_no_difference('LineItem.count') do
post :create, :product_id => products(:ruby).id
end
assert_redirected_to cart_path(assigns(:line_item).cart)
now when I complete the line item tests everything (including listing of cart after add) works as intended.
First: add a unit test for the cart.add_product method
test "cart aggregates line items" do
c = carts(:one)
assert_equal 0, c.line_items.count, "cart items not empty at start of test"
p = products(:ruby)
item = c.add_product(p.id)
assert_equal 1, c.line_items.count, "first product add did not create new line item"
assert_equal 1, item.quantity, "new item quantity not 1"
item = c.add_product(p.id) #hold reference for future testing
assert_equal 1, c.line_items.count, "readd product caused increase in line items count"
assert_equal products(:ruby).id, item.product.id, "a problem with product id between line item and orig"
end
(Note to self: originally tried to do above like:
- assert_difference('c.line_items.count') do
- p = products(:ruby)
- c.add_product(p.id)
- c.save
- end
Note that the assert_difference requires a DB save event. Decided I didn't like that extra dependency on a unit test. Also note that the assert_difference requires a string not an object expression.)
Second: modify line_item_controller test to show aggregation of line items
test "should create/update line_item" do
#original test when just creating new items (iteration D)
assert_difference('LineItem.count') do
post :create, :product_id => products(:ruby).id
end
assert_redirected_to cart_path(assigns(:line_item).cart)
#new test - just repeat old and this time no_difference
assert_no_difference('LineItem.count') do
post :create, :product_id => products(:ruby).id
end
assert_redirected_to cart_path(assigns(:line_item).cart)
now when I complete the line item tests everything (including listing of cart after add) works as intended.
Subscribe to:
Posts (Atom)
