SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    SitePoint Zealot Koobi's Avatar
    Join Date
    Nov 2003
    Location
    Sri Lanka
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Newbie, Error on scaffold

    Hi,
    I've been developing with PHP for about 6 years now but I only began learning ROR the other day.

    I'm trying out this tutorial: http://www.sitepoint.com/article/ruby-on-rails
    I'm upto the point where the author instructs us to start up webrick and view the app (beginning of second page).
    When I do that, I see a page with the following error:

    NoMethodError in List itemsController#index
    undefined method `scaffold' for ListItemsController:Class

    RAILS_ROOT: /var/www/RUBY/ShoppingList

    Application Trace | Framework Trace | Full Trace
    app/controllers/list_items_controller.rb:2

    Request

    Parameters:

    None

    Show session dump

    Response

    Headers:

    {"cookie"=>[],
    "Cache-Control"=>"no-cache"}
    That's what I get when I access: http://localhost:3000/list_items/
    My files are in:
    Code:
    $ pwd
    /var/www/RUBY/ShoppingList

    Using either of the URL's below only gives me a routing error:
    Code:
    http://localhost:3000/ShoppingList/
    http://localhost:3000/ShoppingList/list_items/

    I seem to run into this sort of problem or routing problems quite often but I'm sure I used scaffold in another tutorial yesterday. What am I doing wrong?

    BTW, I'm on Ubuntu 7.10.

    Any guidance would be appreciated
    Thanks.

  2. #2
    SitePoint Zealot Koobi's Avatar
    Join Date
    Nov 2003
    Location
    Sri Lanka
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I just read
    Wikipedia:Scaffold (programming) and I realized that the time when scaffolding worked for me in the past was when I didn't use Dynamic Scaffolding.

    Does this have anything to do with my environment or PATH variable?

    If it helps, the following command returns nothing:
    Code:
    $ set | grep -i ruby

    Thanks.

  3. #3
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That tutorial is out of date, ActiveController's scaffold has been ditched. It was neat, but inflexible, and didn't work much like anything else in Rails. The presence of that error suggests that your setup is fine.

    Scrap what you were doing, and do this instead:

    ruby script/generate scaffold item name:string cost:decimal quantity:integer
    rake db:migrate
    (browser) localhost:3000/items

    The generator will tell you which files were created, check them out and you'll get a picture of how things work.
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  4. #4
    SitePoint Zealot Koobi's Avatar
    Join Date
    Nov 2003
    Location
    Sri Lanka
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, I tried it out but I got an error while raking:
    Code:
    $ rake db:migrate
    (in /var/www/RUBY/ShoppingList)
    == 1 CreateListItems: migrating ===============================================
    -- create_table(:list_items)
    rake aborted!
    SQLite3::SQLException: table list_items already exists: CREATE TABLE list_items ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime DEFAULT NULL, "updated_at" datetime DEFAULT NULL) 
    
    (See full trace by running task with --trace)
    I didn't explicitly create list_items so I'm not sure how that error came up.
    How would I check if such a table already exists? This is my first time using SQLite as well...I've only used Postgres, Oracle and very little MySQL.



    Do you think you could explain the scaffolding part to me please?
    Did you determine the parameters for scaffolding by looking at the sqlite create table query?
    Scaffolding just creates the CRUD operations for the given table fields, right?


    Also, is this:
    Code:
    ruby script/generate scaffold item name:string cost:decimal quantity:integer
    identical to this:
    Code:
    ./script/generate scaffold item name:string cost:decimal quantity:integer

    Thanks for your time.

  5. #5
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you are using the Rails migration system (strongly preferred), it keeps track of what tables are there or not. If you work a little inside and a little outside you can get errors like the one you have. Your earlier work probably put that table there, it is in that article.

    Start the database over, try:
    rake db:drop
    rake db:migrate

    Really, I'd completely start over for exactly this sort of reason. Find a more current tutorial, too.
    rails second_try
    cd second_try
    ruby script/generate scaffold item name:string cost:decimal quantity:integer
    rake db:migrate
    (browser) localhost:3000/items

    Scaffold just stamps a bunch of files onto your site. The db/ one decides what gets changed in the database, app/views/* decides what the pages look like, etc.

    Once the site is up and running look at what was generated and see if you can decide what did what.

    ruby script/generate and
    ./script/generate
    are essentially identical, the former doesn't require the shebang to be correct.
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  6. #6
    SitePoint Zealot Koobi's Avatar
    Join Date
    Nov 2003
    Location
    Sri Lanka
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I agree, it's better to start over...that brings me to another question (hope you don't mind), to start over, is it also sufficient to:
    Code:
    $ rake db:drop
    $ cd ../
    $ rm -rf ShoppingList

    So let me see if I understood this...scaffolding sets up the CRUD features...so I understand why it creates the view files.
    I understand the model for item.
    How about the file in db/migrate? I vi'd into it and it's got a class by this definition:
    Code:
    class CreateItems < ActiveRecord::Migration
    The self.up method defines a table I think...for example:
    Code:
    t.string :name
    And I gather that's from the parameters for scaffolding. What if I wanted more properties for a field...for example, say I wanted the default for the name field to be "Guest" if no name was entered?

    The db:migrate seems to somehow trigger the self.up method of this file.
    Does db:drop trigger the self.down method?

    The items_controller makes sense for the most part...I'm sure I'll understand it better once I get the hang of Ruby.

    Is the following routing created so that the URL http://localhost:3000/items leads me to the appropriate page?
    Code:
    route  map.resources :items
    That's about it...I think I can get the rest of it, thanks again.

  7. #7
    SitePoint Member
    Join Date
    Oct 2007
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Koobi View Post
    And I gather that's from the parameters for scaffolding. What if I wanted more properties for a field...for example, say I wanted the default for the name field to be "Guest" if no name was entered?
    Code:
    t.string :name, :default => 'Guest'
    Should do it, IIRC.

    The db:migrate seems to somehow trigger the self.up method of this file.
    Does db:drop trigger the self.down method?
    Yep.

    Is the following routing created so that the URL http://localhost:3000/items leads me to the appropriate page?
    Code:
    route  map.resources :items
    Yeah, map.resources :whatever will create a complete set of RESTful routes for CRUD operations on :whatever. Use 'rake routes' from the command prompt to see all your available routes.

  8. #8
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    SqlLite databases are kept in the db/ directory, so deleting the project deletes everything.

    Unless I'm mistaken, db:drop triggers a DROP sql statement, essentially nuking the database.
    db:migrate VERSION=X can walk up and down the migration list.

    I like to specify defaults in the model rather than the database.
    Code Ruby:
    class Item < ActiveRecord::Base
      def name
        super or 'default'
      end
    end

    That's just overriding the default "name" method (which comes from the database) and saying that if the old name (super) returns nothing, use 'default'. That way you can tell the difference between an item with no name, and an item with the name "default".

    A lot to digest initially, but you are getting a lot done for you.
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  9. #9
    SitePoint Zealot Koobi's Avatar
    Join Date
    Nov 2003
    Location
    Sri Lanka
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I didn't know you could create a method to do that for you...so you're saying if a name is not entered in the form field, the model accesses the method you typed out and uses default? I don't understand how that works from the model you've shown me, maybe I will once I learn more Ruby/ROR?

    I have another problem...I'm trying out this tutorial right now: http://www.jhl.it/Courses/LUGPC9.html

    If you scroll down to the part that reads "Our First User", I've done all of that but when I attempt to create a new user, I get the following error:

    Code:
    undefined method `salt=' for #<User:0xb761a820>
    and
    Code:
    /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/attribute_methods.rb:200:in `method_missing'
    app/models/user.rb:19:in `password='
    app/controllers/users_controller.rb:43:in `new'
    app/controllers/users_controller.rb:43:in `create'

    This is my app/models/user.rb:
    Code:
     16   def password=(pword)
     17     @password = pword.strip
     18     return if @password.length < 6 || @password.length > 40
     19     self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{rand.to_s}--")
     20     self.salted_password = User.encrypted_password(self.salt, @password)
     21   end
    Should salt be defined in my class or is it inherited from a gem?

    Something weird I noticed was that the sha1 gem apparently exists:
    Code:
    $ gem which sha1
    /usr/lib/ruby/1.8/sha1.rb
    but I get an error when I attempt to look at its contents:
    Code:
    $ gem contents sha1
    Unable to find gem 'sha1' in default gem paths
    
    Directories searched:
    /usr/lib/ruby/gems/1.8/specifications

    but doing a check reveals no errors:
    Code:
    $ gem check sha1

    Have I done anything wrong here?

  10. #10
    SitePoint Member
    Join Date
    Oct 2007
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by samsm View Post
    Unless I'm mistaken, db:drop triggers a DROP sql statement, essentially nuking the database.
    db:migrate VERSION=X can walk up and down the migration list.

    Oops, yeah, it does. Not quite sure what I was thinking there.

  11. #11
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Koobi View Post
    I didn't know you could create a method to do that for you...so you're saying if a name is not entered in the form field, the model accesses the method you typed out and uses default?
    Code Ruby:
    class Item < ActiveRecord::Base
    end
     
    # ...
     
    @item = Item.find :first
    @item.name

    That code pulls an item from the database. If that item has a name, that last line would return it ... if it didn't, it would return nil which is kind of like boolean false. That's the default behavior, what you get for free ... ActiveRecord reads the table and creates def column_name methods for each column.

    One of the neat things you can do with Ruby is reopen a method and change it, in this case overwriting that default ActiveRecord method with:
    Code Ruby:
    super # do everything the old def name did
    or
    'default' # never gets run unless the above returns nil
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  12. #12
    SitePoint Zealot Koobi's Avatar
    Join Date
    Nov 2003
    Location
    Sri Lanka
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    great, thanks for all the help, the both of you
    i learnt a little ruby over the last 4 days and now things make a lot more sense


    :edt:
    one more thing though, you're saying I should use scaffold for every rails app I create that has CRUD functions, right? Is that better than using script/generate to create the model and controller separately?

  13. #13
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Whichever way you want. If scaffold starts you where you want to be, do that.
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •