Re: What is the best modelstructure and routes?

Just a further note on testing
don;t be firghtened, tests are easy and Rails generates lots of them for you.
Do yourself a favour and from the command prompt in the root folder of your app run the following

rake test

show me what you get

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: What is the best modelstructure and routes?

This is what I get:

$ rake test
(in C:/Documents and Settings/rb1/My Documents/RoR/victaulic_productsite)
Run options:

# Running tests:



Finished tests in 0.000000s, NaN tests/s, NaN assertions/s.

0 tests, 0 assertions, 0 failures, 0 errors, 0 skips
Run options:

# Running tests:

E

Finished tests in 0.656250s, 1.5238 tests/s, 0.0000 assertions/s.

  1) Error:
test_should_get_new(SessionsControllerTest):
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'number' in 'field list': INSERT INTO `customers` (
`number`, `email`, `address_1`, `address_2`, `zipcode`, `city`, `country_id`, `contact_person_id`, `id`) VALUES (
1, 'MyString', 'MyString', 'MyString', 1, 'MyString', 1, 'MyString', 980190962)
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract_mysql_a
dapter.rb:245:in `query'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract_mysql_a
dapter.rb:245:in `block in execute'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract_adapter
.rb:280:in `block in log'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activesupport-3.2.8/lib/active_support/notifications/instrumenter.rb:20:i
n `instrument'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract_adapter
.rb:275:in `log'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract_mysql_a
dapter.rb:245:in `execute'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/mysql2_adapter.r
b:211:in `execute'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/databas
e_statements.rb:277:in `insert_fixture'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:502:in `block (5 levels)
 in create_fixtures'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:501:in `each'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:501:in `block (4 levels)
 in create_fixtures'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:500:in `each'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:500:in `block (3 levels)
 in create_fixtures'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:492:in `each'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:492:in `block (2 levels)
 in create_fixtures'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/databas
e_statements.rb:192:in `transaction'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:491:in `block in create_
fixtures'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract_mysql_a
dapter.rb:232:in `disable_referential_integrity'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:476:in `create_fixtures'

    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:895:in `load_fixtures'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/fixtures.rb:849:in `setup_fixtures'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:429:in `_run__4686951
36__setup__190481830__callbacks'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:405:in `__run_callbac
k'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:385:in `_run_setup_ca
llbacks'
    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:81:in `run_callbacks'

    c:/Ruby193/lib/ruby/gems/1.9.1/gems/activesupport-3.2.8/lib/active_support/testing/setup_and_teardown.rb:35:i
n `run'

1 tests, 0 assertions, 0 failures, 1 errors, 0 skips
Errors running test:functionals! #<RuntimeError: Command failed with status (1): [c:/Ruby193/bin/ruby.exe -I"lib;
test" -I"c:...]>

I've read everything you've said, I'm now creating the complete linking etc. to have a clear view of what I want to achieve. I've had it all in my head, the database structure was already on paper.

Do you have any good examples that are for you most useful and have the quality a spec should have?

Greetings

Re: What is the best modelstructure and routes?

I use pencil, paper and rubber smile, It's what I was taught way back in the 80's, call me a dinosaur but it works for me smile I have never found a piece of software that really meets my needs.
Actually, that's not strictly true, for very complex or very large projects I use a number of design techniques, jacksons structured design and UML mainly. I loe UML because you take just the bits that work for you and do it your way at the same time others can understand it but the real bous is that it kida naturally leads you down an OO route.

You should be fine with paper and pencil and write out use cases
http://en.wikipedia.org/wiki/Use_case

You don't have to be formal, just write down clearly a list of actions that a user can perform. Where they go to perform the actions, what they see when they get there, what ionformation they can complete, what information they HAVe to complete and document the effect this has on the system.

A simple example

Make a up of tea

1) User visits mysite/make_tea
2) User sees a kettle, a tap, milk, sugar, cup
3) User only needs to fill kettle if kettle needs filling
4) User boils kettle
5) User puts tea in cup - Ooops, I forgot to mention that User sees tea in step 2. Must add that in!
6) Users purs boiling water into cup.
7) User might want to add sugar (Note to self - Perhaps a check box to add sugar and prompt user to state how many spoonfulls - Ooops - I forgot to mention that user also sees a teaspoon in step 1!)
8) User might want to add milk - Pour milk function will need a number of millileters as a param
9) User makes the above selections and submits the form.
10) Need to describe what happens when the form is submitted.
If successful
  11) User is directed to my_site/drink_tea
else
  12) User sees a message "Couldn't make tea! and an explanation of why.
  13) User is given an opportunity to correct mistakes
ens
14) ... And so it goes on

But really, just do what suits you.

I would go on to describe a kettle and it's functions and attributes. A Quick example

Kettle,
A Kettle holds water
A Kettle has a size.
A Kettle can be boiled.
A Kettle pours water

Things a kettle can do are functions, or methods, if you prefer. things a kettle has are attibutes (Columns in a table)

The above can easily be converted into a structured diagram of some description but that's not what is important. The really important thing here is that you think about the whole aspect of the application and you make just enough notes to prompt you into going into further detail if you need to.
The devil is always in the detail. Those ommissions regarding spoon and tea are what classically happens when you write a program to make tea from your head rather than from a piece of paper. I know! It's what I just did! Those were genuine ommissions as I wrote it out from my head.

Writing things out in this kind of way is difficult because you are forced to think about every spect of your app, and when you are quite happy that you understand how to make a cup of tea you wonder if it's worth the pain of having to think through all the scenarious, like how to make sure that the kettle won't switch on unless it has water, what happens if there is not enough water to make a cup after it has boiled. Trust me, it will save you a lot of head scratching and refactoring. Remember, it takes time to write code. It takes a lot less time to write a spec.

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: What is the best modelstructure and routes?

Following up on the above, I missed the obvious.
I do this all the time http://railscasts.com/episodes/275-how-i-test
It's the BEST form of spec you can do as it actually tests your code not only works but meets your requirements

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: What is the best modelstructure and routes?

So you mean, the specs like "create a cup of tee" is in the rails test environment test "create a cup of tee"
I have to say if I use guard or like want to change something or check something with rake, it takes ages! rake test took 3 minutes to complete... that's a lot right?
Maybe there is something wrong in my settings what make this so slow.

Anyways, I've now created the a view process, together with some specs. Now I just have to add all the written specs into test models in my rails project like Ryan Bates discusses in his test-screencasts.

Re: What is the best modelstructure and routes?

So you mean, the specs like "create a cup of tee" is in the rails test environment test "create a cup of tee"

Yup!

I have to say if I use guard or like want to change something or check something with rake, it takes ages! rake test took 3 minutes to complete... that's a lot right?

Yup! That's too long. I guess you are using Windows then?

There are things that can be done to improve performance
Try adding :bundler => false to both rspec-guard and spork-guard configurations in Guardfile. There are other things that can be done like using spork - http://railscasts.com/episodes/285-spork?view=asciicast

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: What is the best modelstructure and routes?

I will look on those options.

For the moment, I want to know something extra.

For my product filters, I want to do something like this:

/products/:maingroup
/products/:maingroup/:class
/products/:maingroup/:class/:itemgroup

The first would than go to the page that shows alle categories (within that maingroup: Motoric/Electric).
The second would than show all itemgroups within that class that is situated in the maingroup
The last one shows the product that represents that itemgroup.

Still working on that one (1) database as we discussed before, is that possible?


Greets!

Last edited by ReBa (2012-10-26 09:24:11)

Re: What is the best modelstructure and routes?

And by the way, the spork & rspec on guard are working very good! Testing and setting the test environment up time is reduced by 3/4! --> Thanks a lot!

The only thing is that in my opinion, the testing environment is not so usefull.
I'm already trying half a day on testing and getting errors.
Not because of errors in my programming code, but just because the testing code is so damn extensive. Maybe after a while this will have some advantages, but for now, and that's the main problem for this, it is not going as I want and on what time I'm trying to win time with that, it is much, and really much faster just enabling my server and do it the manual way.

For exameple, my login... I have following login:

describe "signup" do
    it "has right data" do
      visit signup_path
      fill_in :id, :with => 2110001
      fill_in :name, :with => "AVK POLSKA Sp. zo.o."
      fill_in :email, :with => "my.email@victaulic.be"
      fill_in :email_confirmation, :with => "my.email@victaulic.be"
      click_button "Create account"
      current_path.should eq(login_path)
    end
end

which is straight from my database copy-paste... and it gives errors! While there aren't any when I try it manually. It gives that ID and Name aren't matching in the database, whilst they are definitely matching. I've checked again and again. So I have to make an error somewhere else I guess?

So what and how do I know what is the problem? It just says:

Failure/Error: current_path.should eq(login_path)

       expected: "/login"
            got: "/signup"

I'm getting zero output from this, except that it is being redirected to the same page as from where the test came. But no more...

Last edited by ReBa (2012-10-31 10:33:14)

Re: What is the best modelstructure and routes?

Sorry for the delay in responding.
You have

click_button "Create account"
current_path.should eq(login_path)

Which tells me that after clicking the "Create account" button you are expecting to be taken to the /login url
and your error is

Failure/Error: current_path.should eq(login_path)

      expected: "/login"
            got: "/signup"

Which tells me that you actually ended up at the /signup url

I'm guessing that if you looked at the action you are taken to when you press the "Create account" button you will see that if an error occurs you re-render the signup page.

You say that the following

      fill_in :id, :with => 2110001
      fill_in :name, :with => "AVK POLSKA Sp. zo.o."
      fill_in :email, :with => "my.email@victaulic.be"
      fill_in :email_confirmation, :with => "my.email@victaulic.be"

Is taken directly from your database

So I'm guessing that you have a validation in your user model that is failing based on the fact that you can not sign up a new account that already has some of those exact same details.
Which indicates to me that the validataions are working just fine and that your test is working just fine, it's just that you are checking for the wrong path.
Of course you are still left with no test to check for a successful signup but that's ok, just use unique details for the fill in's in a new test

I'm impressed with how far you have got with testing, keep it up smile The benefits will soon become clear,

Now for a little criticism, You seem to be filling in a users Id on the signup page.
The user shuld never know their ID and an ID should NEVER appear in a form.

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: What is the best modelstructure and routes?

No problem for the late respons, had holliday anyway the last week smile
Thanks for the help!

jamesw wrote:

Now for a little criticism, You seem to be filling in a users Id on the signup page.
The user shuld never know their ID and an ID should NEVER appear in a form.

Maybe the signup isn't completely clear to you. Let me try to extend the information:

A customer (that is already a customer of the company) has to sign in to the website. As there aren't any extra customers created on the website, only by an external database of the company which holds all customers.
A customer knows this things:

   id = customernumber (which he can find on his invoices)
   name (also on the invoices)
   email (can be something else than what is in the database)

So if a customer wants to go to this customer portal, he needs his customer number and the name of the company. When he signs up, an email is sent with his credentials and the corresponding contact person within the company receives an email with the notification that the customer from a certain company linked to the internal database has accessed the portal. If the contact person doesn't trust the corresponding e-mail, he/she is able to or deactivate or remove this person from the database.

So here is another example:

it "has wrong data and afterwards good data" do
      visit signup_path
      fill_in :id, :with => 2110001
      fill_in :name, :with => "AVK POLSKA Sp. zo.o."
      fill_in :email, :with => "remi.battaille@victaulic.be"
      fill_in :email_confirmation, :with => "remi.error@victaulic.be"
      click_button "Create account"
      current_path.should eq(signup_path)
      page.should have_content("Email doesn't match confirmation")
      fill_in :email, :with => "remi.battaille@victaulic.be"
      fill_in :email_confirmation, :with => "remi.battaille@victaulic.be"
      click_button "Create account"
      current_page.should eq(login_path)
end

This gives following return:

 1) customers signup has wrong data and afterwards good data
     Failure/Error: page.should have_content("Email doesn't match confirmation")
       expected there to be content "Email doesn't match confirmation" in "Victaulic customer portal\n\t\n\t\tHome\n\t\t\n\t\t[b]The customer w
ith this specifications was not found...[/b]\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\t\tPlease sign up to access the customer portal\n\t
\n  \t\n  \t\tId\n  \t\t\n  \t\n  \t\tName\n  \t\t\n  \tPlease ad a valid e-mail to receive your credentials:\n  \t\n  \t\tEmail\n  \t\t\n  
\t\n  \t\tEmail confirmation\n  \t\t\n  \t\n  \t\t\n  \n\n"
     # ./spec/requests/customers_spec.rb:45:in `block (3 levels) in <top (required)>'

As highlighted, the problem is that it shouldn't be "The customer with this specifications was not found..." but "Email doesn't match".

Although I am definitely sure that my customer is right! He just can't find him in the database, as you see for the specs.

def create
    @customer = Customer.new()
    @customer.fill_standard(params[:customer][:id],params[:customer][:name], params[:customer][:email],params[:customer][:email_confirmation])
    
    dbCustomer = Customer.where("id = ?", @customer.id).first
    if dbCustomer
      #CUSTOMERNUMBER CORRECT
      #Check if the input is matching!
      if @customer.id == dbCustomer.id && @customer.name == dbCustomer.name
        #INPUT IS MATCHING
      else
        #INPUT MATCHING FAILED
        #Give message there is no such customer in the database
        flash[:notice] = "The customer with this specifications was not found..."
        redirect_to signup_path
      end
   else
      #CUSTOMERNUMBER IS NOT CORRECT
      #Give message there is no such customer in the database
      flash[:notice] = "The customer with this specifications was not found..."
      redirect_to signup_path
   end
end

The tests are working with the test environment yes? But why doesn't it allow this signup than??
I'm somewhat in the dark here although I understand my test code and what it does. Just not why he is saying the customer specifications are wrong...

Re: What is the best modelstructure and routes?

How are you getting your data into the test database?

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: What is the best modelstructure and routes?

I've made an exact copy of the working development database

Re: What is the best modelstructure and routes?

How?
The test database gets cleared out before every test run

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: What is the best modelstructure and routes?

Ow, that will be the problem then?

There has to be something in my "customer" table, because it is the standard table for all my customers.
How do I test that than with included customer?

First create a customer and than continue?

Re: What is the best modelstructure and routes?

Factory girl is a superb way to set up test data. It gives you complete control over the data you wish to test
http://railscasts.com/episodes/158-fact … es-revised
Or the older free cast
http://railscasts.com/episodes/158-fact … t-fixtures

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: What is the best modelstructure and routes?

I will look into factory girl (I've seen some things about it but I'm still not confortable with the way of working with it)

As I asked before (but unfortunately didn't get an answer on), I will ask my question again on my products:

For my product filters, I want to do something like this:

/products/:maingroup
/products/:maingroup/:class
/products/:maingroup/:class/:itemgroup

The first would than go to the page that shows alle categories (within that maingroup: Motoric/Electric).
The second would than show all itemgroups within that class that is situated in the maingroup
The last one shows the product that represents that itemgroup.

How to do this with routings and my products_controller?

This would be a very great help if I understand this part!

Re: What is the best modelstructure and routes?

As always with a powerfull language there are many different ways of achieving the same result. The best approach really depens on how you want the user experience to be.
Do you want links (menu) on the products page? Or perhaps a drop down selection list?
Whichever way you go, you have a choice to make over the url (controller/actions) that you want involved.
You can link back to the products index action passing in additional params that the index action can then use to filter the results or you can link to a different controller/action that takes in whatever params and filters accordingly.

To achieve either you will need to send a http post request (Button or javascript) back to the server so you will need a route that accepts the params you want which could look sommethin like this

resources :products do
  collection { post :search, to: 'products#index' }
end

then in the products index action you would check for the search param

def index
  if params[:search].blank?
    @products = Product.all
  else
    @products = Product.where(:whatever_field => params[:search])
  end
  ...

end

This can be applied to any route.
Another option is to use nested routes

resources :products do
  resources :maingroup do
    resources :class
  end
end

each nested route will automatically expect an id for the parent
so to get to the class route you would do
/products/1/maingroups/1/classes
That would get you the product with an id of 1 and a maingroup with an id of 1
Hope that makes sense

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: What is the best modelstructure and routes?

Yes, I was thinking on nested routings.

So when I have selected the maingroup :

/products/maingroup1

I want to see:

-category1
-category2
-...

Which will go to /products/maingroup1/category1, like you say with nested groups.
But as I hopefully understand, I can't nest more than 2 levels, right?

So it would be like:

resources :products do
  resources :maingroups do
    resources :categories
  end
end

recourses :categories do
  resources :itemgroups
end

And I will get my wanted structure right? Or is this to complicated?

EDIT
As I also tried what I am asking (dumb not to try this before posting) I get following routes:

product_maingroup_categories GET    /products/:product_id/maingroups/:maingroup_id/categories(.:format)          categories#index
                                POST   /products/:product_id/maingroups/:maingroup_id/categories(.:format)          categories#create

But that is not what I want. I want it like this: /products/maingroups/:maingroup_id/categories/:categorie_id/itemgroups/:itemgroup_id

--> Now I am looking at a specific itemgroup
I hope that makes any sense?


Greets (and thanx!)

Last edited by ReBa (2012-11-05 08:06:35)

Re: What is the best modelstructure and routes?

I can't nest more than 2 levels, right?

Not sure why you would think that! There is no limit except that imposed by HTML URL maximum length.
It's not good practice to nest too deeply but only from an SEO point of view really and that doesn't apply here as it's a closed site - Speaking o which, I meant to mention this earlier.
Make sure your site is totally locked down to use SSL (HTTPS) when in production.
It's dead simple to do. Just add a force_ssl => true to your application controller, but remember to set up an ssl certificate on your host

But that is not what I want. I want it like this: /products/maingroups/:maingroup_id/categories/:categorie_id/itemgroups/:itemgroup_id

As far as I can tell the only difference between what you want and what you get is the product_id right?
To get rid of that make the products a name space rather than a resource

namespace :products do 
    resources :maingroups do
# etc ..
    end
end

This however would interfere with product maintenance routes (If there are any) like product/new etc...
So you might want to consider changing the name of the name space.
A name space is just a folder inside your controllers folder that will contain nothing other than the folders for the nested controllers. This is typically used for an admin type of solution where you want an admin area and all controllers relating specifically to administrative tasks inside that area.

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: What is the best modelstructure and routes?

jamesw wrote:

As far as I can tell the only difference between what you want and what you get is the product_id right?
To get rid of that make the products a name space rather than a resource

|-> Totally correct smile

I've read some things about the namespace and understand the main purpose for what it is being used.
And yes, this seems to be the best way to work with form me as there won't be a product that has different categories.

This however would interfere with product maintenance routes (If there are any) like product/new etc...

A product will never be adapted from the website. Nobody will be able to do that, even me. The products table will be updated weekly by an intern. So namespace should be the best option I suppose?