$ cd myProject $ rails new blog./gemfile ./app/ assets/[images, javascript, stylesheet] controllers, models, views ./config/ databse.yml route.rb ./db/ datasbe schema, migration files ./test/ $ cd blog $ rails g controller posts #g OR generate, naming convention: should be plural. action is an individual page for your controller( respected view files for your controller). ./app/controllers/posts_controller.rb ./test/controllers/posts_controller_test.rb ./app/helpers/posts_helper.rb ./test/helpers/posts_helper_test.rb ./app/assets/javascripts/posts.js.coffee ./app/assets/stylesheets/posts.css.scss $ vim app/controllers/posts_controller.rb def index # add index action (route) / index page end $ touch ./app/views/posts/index.html.erb # create. erb: Embedded ruby. use html, embedded ruby, javascript, etc.... in your view files$ vim ./app/views/posts/index.html.erb <h1>Our Blog</h1> <p>Hello World!</p> create a route to access this in the browser $ vim ./config/routes.rb # routes for our posts resource: think of posts as resource where you can create, retrieve, destroy,... resources :posts # create a set of 7 routes for us one of which is 'index', the total are index , show , new , create , edit , update and destroy (a.k.a actions)# create a set of routes by calling resources and passing the symbol with the name of our controller which is posts http://localhost:3000/posts Takes us right into our index action (or view) Ctrl+u to view source code $ rails g model post title:string content:text # model is in singular form (versus controller which is in plural form) ./db/migrate/20130706161915_create_posts.rb #migration file: timestamp_ create_posts table in the database: migration is a way to deal with DB rather than writing SQL. Table name is in plural form, hence posts #creates title, content and timestamps (created at, updated at) ./app/models/post.rb #post model $ rake db:migrate # run the appropriate migration (create the SQL table)./test/models/post_test.rb ./test/fixtures/posts.yml $ vim ./app/models/post.rb attr_accessible :title, :content #specify which fields to be accessible [upon updating the posts model (records table)]: which fields are allowed to be saved via mass assignment? pass arguments of field names #@deprecated: in rails 4.0 use strong parameters which moves authorization/authentication to control # to create a post, there are two ways: first create a post object # we use symbols :title, :content to have only one string representing each which will later on makes things easier for comparison or addittion or hash modification. It's like String.intern() in java > post = Post.new(:title => "Our first post", :content => "Content for our first post.") # create post object > post.save # save the object into the datasbe > Post.create(:title => "Our second post", :content => "Content for our second post.") # create a post entry in database in one step instead of two steps (above) > posts = Post.all # retrieve all posts > post = Post.find(2) # get post with id = 2 > post.title > post.content > post.title = "our 2nd post" # update in two steps > post.save > post.update_attribute(:content, "Content for our 2nd post.") # update in one step > post.update_attributes(:title => "Our Second Post", :content => "Content for our second post.") # update multiple attributes > post.find(2) # notice the difference in create time and update time > post.destroy # delete second post > post.find(2) # error > exit $ rake routes # generate routes (specified in ./config/routes.rb). 7 differnet actions for our Posts controller # index: display all of our posts # show display an individual post # new: display a form to submit a new form # create: dosn't have a view. just saves the post in the datasbe, then redirect to a different page # edit: display a form for editing a post # update to actually doing the updating in the databse. It doesn't have a view file. then redirect to a differnet page # destroy: delete a post. Like create/update, does not have view. A link to destroy action to destroy a post, redirects to a differnet page or render something else Prefix Verb URI Pattern Controller#Action posts GET /posts(.:format) posts#index POST /posts(.:format) posts#create new_post GET /posts/new(.:format) posts#new edit_post GET /posts/:id/edit(.:format) posts#edit post GET /posts/:id(.:format) posts#show PATCH /posts/:id(.:format) posts#update PUT /posts/:id(.:format) posts#update DELETE /posts/:id(.:format) posts#destroy We also get named routes that refereing to tese routes posts_path refer to index action new_post_path new action. create a link to new_post_path and that will link them to the new page edit_post_path(1) takes a parameter of hte post that you want to edit, rediect to a page to edit post w/ id 1 post(1) take you to page to viw post 1 $ vim ./app/posts_controller.rb #----------- 7 different actions def show # show indivisual post end def new # display a anew form to create a new post end def create # form from the new action will submit to and this will save the post into the datasbe end def edit # display a form for editing the pst end def update # to actually updatign a post. the form on edit page ill submit to the update action and this will update that post in the datasbe end def destroy # to delete a post end $ touch ./app/views/posts/show.html.erb $ touch ./app/views/posts/new.html.erb $ touch ./app/views/posts/edit.html.erb To change our posts index page to display all our posts instead of the HelloWorld message In the controller change the index action to retrieve all of the posts and then make them available inside of the view file and then we can display them to the browser. To send something to your view you can create an instance variable $ vim ./app/controllers/posts_controller.erbdef index @posts = Post.all # get all posts and store them in this te @posts instance variable. then we can have access to this variable inside our view file to display these posts in the browser end $ vim ./app/views/index.html.erb # write embedded ruby inside <% %> you can write ruby code, when you want to output somethign to the browser use <%= %> $ rails s # start the server<h1>Our Blog</h1> <% @posts.each do |post| %> <!-- loop through posts. posts is a hash that is retrieved from the datasbe in the ./app/controllers/post_controller.rb in the index action method.--> <h2> <%= post.title %> </h2> <p> <%= post.content %></p> <hr/> <% end %> <!-- close the loop block--> http://localhost:3000/posts # there will be one post as we deleted the second post. while the server is running open another terminal $ rails c $ Post.create(:title => "Our second post", :content => "Our secodn post content") Refresh browser View just one post at a time. 'show' view. $ vim ./app/controllers/posts_controller.rb def show # show indivisual post @post = Post.find(params[:id]) # Params hash and grab the id that was passsed-in through the URL. # Note that INSTANCE VARIABLES ARE ACCESSIBLE INSIDE OUR VIEW FILE. end $ vim ./app/views/posts/show.html.erb <h1><%= @post.title %></h1> <p><%= @post.content %></p> <small><%= @post.created_at %></small> modify index to include links to view the blog $ vim ./app/views/posts/index.html.erb <h1>Our Blog</h1> <% @posts.each do |post| %> <!-- loop through posts. posts is a hash that is retrieved from the datasbe in the ./app/controllers/post_controller.rb in the index action method.--> <h2> <%= link_to post.title, post %> </h2> <!--link_to method text, id or object to get its show URL--> <p> <%= post.content %></p> <hr/> <% end %> <!-- close the loop block--> Creating forms, redirecting users, rendering views, displaying flash messages. Add a link in the index page to link to our posts new action which is going to be used to add a new post. 'new' action used to display a form so that one can create a post Creating forms first: edit the index page to add a link to this 'new' action $ vim ./app/views/posts/index.html.erb <p><%= link_to "Add a New Post, new_posts_path" %></p> <!-- link to the named route to the new action --> $ vim ./app/views/posts/new.html.erb <h1>Add a New Post</h1> This link will take us to http://localhost:3000/posts/new-- Now, let's add a form on the above page so that we can actually submit the post $ vim ./app/controllers/post_controller.rb def new @post = Post.new # this will accessible in our 'new' action view end $ vim ./app/views/posts/new.html.erb <h1>Add a New Post</h1> <%= form_for @post do |f| %> <!--Pass to it the empty post object that we created in the 'new' action in the controller. It takes a block that is used to creatign a form.--> <!--Here we have access to this local f variable. Create form fields for enterign a new post.--> <p> <%= f.label :title %> <br/> <!--Create a label tag for the title.--> <%= f.text_field :title %> </p> <p> <%= f.label :content %> <br/> <!--for the content.--> <%= f.text_area :content %> </p> <p> <%= f.submit "Add a New Post" %> <!--Submit button.--> </p> <% end %> <!--end the block--> view it at http://localhost:3000/posts/new -- Question: in the previous step we didn't do anything with the empty post object that we created in the 'new' action in the controller inside the 'new' action view? Now get the created new post object at 'create' action. Grab the form values that were submitted and save it in the database. $ vim ./app/controllers/post_controller.rb def create # form from the new action will submit to and this will save the post into the datasbe @post = Post.new(params[:post]) #he actual post information that was submitted throguh the form. And we grab that through the params hash and we grab that post information. Now we have access to the post object that we save to the databse. if @post.save # returns true or false if save was successfull redirect_to posts_path, :notice => "Your post was saved." # if was successfully saved. redirect to the named rout for the index action view. # notice is a flash message and we need to make sure we handle flash messages. Edit the layout file. else render "new" # save has been usuccessfull. render the new form again so that the user can try again end end $vim ./app/views/layouts/application.html.erb <%= flash.each do |key, value| %> <!--We have access to this flash hash amd loop through it and pass it a block access its key and values--> <p><%= value %></p> <!--key is hte type of message, value is The actual message itself.--> <% end %> Edit posts Add Edit link in index view for each post. $ vim ./app/views/posts/index.html.erb <p> <%= link_to "Edit", edit_post_path(post) %></p> # in the for loop going through each post $ vim ./app/views/posts/edit.html.erb <h1>Edit Post</h1> Create the form $ vim ./app/views/posts/edit.html.erb <h1>Edit Post1</h1> <%= form_for @post do |f| %> <p> <%= f.label :title %> <br/> <%= f.text_field :title %> </p> <p> <%= f.label :content %> <br/> <%= f.text_area :content %> </p> <%= f.submit "Update Post" %> <% end %> $ vim ./app/controllers/post_controller.rb def edit # display a form for editing the pst @post = Post.find(params[:id]) end def update # to actually updatign a post. the form on edit page ill submit to the update action and this will update that post in the datasbe @post = Post.find(params[:id]) if @post.update_attributes(params.require(:post).permit(:title, :content)) redirect_to posts_path, :notice => "Your post has been updaetd" else render "edit" end end The link would be in this form http://localhost:3000/posts/6/edit Delete Posts Add delete link to each post $ vim ./app/views/posts/index.html.erb <p> <%= link_to "Edit", edit_post_path(post) %> | <%= link_to "Delete", post, :confirm => "Are you sure", :method => :delete %> <!--Confirm is for a javascripy popup. method is to go to the destroy action rather than the show action--> </p> $ vim ./app/controllers/post_controller.rb def destroy # to delete a post @post = Post.find(params[:id]) @post.destroy redirect_to posts_path, :notice => "Your post has been deleted." end Validation. e.g. empty post title $ vim ./app/views/posts/new.html.erb and $ vim ./app/views/posts/edit.html.erb <% if @post.errors.any? %> <h2>Errors:</h2> <ul> <% @post.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> <% end %> No difference. render :template => 'some/thing' is the same as just render 'some/thing', as well as the same as render :action => 'thing' if we are in the 'some' controller. From RubyOnRails guides, all of the above is the same :
$ rails generate controller FooBars baz quux $ rails destroy controller FooBars baz quux # these two commands undo Controls $ rake db:migrate VERSION=0 # the version numbers come from listing the migrations sequentially. |
Software Engineering ➼ Machine learning ➼ Data Science ➼ Product Leadership 🎯 > Tools - Business > Ruby >