Web Application Frameworks - MVC
Denis Helic
IICM, TU Graz
Separation of Concerns (1)
- Core design pattern of all software engineering
- Easily supported by object-oriented software development
- Definition by Edsger Dijkstra
We know that a program must be correct and we can study it from that viewpoint only; we also know that is should be efficient and we can study its efficiency on another day [...] But nothing is gained - on the contrary - by tackling these various aspects simultaneously. It is what I sometimes have called "the separation of concerns" [...]
"On the role of scientific thought"
Separation of Concerns (2)
- You want to isolate different aspects of a software application from each other
- You can work on each aspect in details
- You can be consistent within each aspect
- At a single moment you work on a single aspect (e.g., you are not distracted with other aspects)
- Also, a basis for the team work (e.g., different teams work on different aspects)
Separation of Concerns (3)
- Divide-and-conquer method of designing algorithms
- Applied to developing software applications
- OO principles easily support SOC
- Classes, objects, encapsulation isolate one aspect from another
- If interfaces are clearly defined you can work on different aspects in isolation
- Architectural and design patterns are also used to achieve SOC
Benefits of SOC
- Improved comprehension of the application domain
- Reduced complexity
- Component (aspect) integration
- Reuse
- Adaptibility, customization (through component exchange)
User-oriented database applications - SOC
Model-View-Controller (1)
- Model-View-Controller is a particular design pattern that supports SOC
- It was invented in the early days of GUIs
- To decouple the graphical interface from the application data and logic
- GUI is further separated into data presentation and users' input
- Invented at Xerox Parc in the 70's
Model-View-Controller (2)
- The first appereance in Smalltalk-80
- One of the first OO languages
- Pure OO language, i.e., everything is an object
- MVC invented by Trygve Reenskaug: Original documentation
Model-View-Controller (3)
Model-View-Controller (4)
- Controller
- Handles user input (e.g., mouse clicks, keyboard,...)
- Updates the model
- Instructs the view to redraw itself
Model-View-Controller (5)
- View
- Presents the model in a specific way
- Note different views for the same model
- Very important not only in GUIs but also in Web applications (e.g., XHTML, PDF, etc.)
Model-View-Controller (6)
- Model
- Contains the data and application logic
Model-View-Controller (7)
- Very easily accomplished with an OO programming model
- Objects encapsulate the data
- Objects implement behaviour (as methods)
- Interaction between different objects (i.e., invoking methods) supports the application logic
Model-View-Controller (8)
- Where does the data come from?
- If in memory - everything is covered
- If in the file system or in a DBMS
- We need a special Data Management module
Model-View-Controller (9)
Model-View-Controller (10)
- A special case of the MVC uses Observer design pattern
Model-View-Controller (11)
- When the model changes it notifies the views about the change
- All views redraw as the result of the notification
- Until Ajax not applicable in a Web application
- Page-oriented applications
- You need a user request for each particular view (e.g., HTML, PDF,..)
- With Ajax it is possible (Asynchronous request)
- It improves the responsiveness of a Web app tremendously
Model-View-Controller (12)
- The purpose of the controller is not to separate the model from the view
- E.g., in GUI applications the purpose of the controller is to handle user events
- To achieve this separation another design pattern is needed
- Typically acheived by means of the Observer pattern
MVC: An example with Observer pattern (1)
- A simple GUI Java application using MVC
- The example uses Observable/Observer pair from java.util
- Subclasses of the Observable class can notify observers about changes in their state
- Implementation classes of Observer need to implement update() method to react to the changes
- Observer is a Java interface
MVC: An example with Observer pattern (2)
- Model
- SimpleModel holding a single integer value
- getValue() and setValue() methods to manipulate the model
- The value must be in the range [0,100]
MVC: An example with Observer pattern (3)
final public class SimpleModel extends Observable {
...
public void setValue(int value) {
if ((value > 100) || (value < 0)) {
throw new IllegalArgumentException("The value must be ..");
}
value_ = value;
setChanged();
notifyObservers();
}
...
}
Source code
MVC: An example with Observer pattern (4)
- View
- Holds a reference to the model
- Manages a GUI widget to represent the model value
- Reacts to change notifications from the model
- It is an abstract class, where subclasses manage different GUI widgets
MVC: An example with Observer pattern (5)
public abstract class SimpleView implements Observer {
protected JComponent widget_;
public void update(Observable observable, Object arg) {
updateView();
}
abstract public void updateView();
...
}
Source code
MVC: An example with Observer pattern (6)
final public class SimpleTextFieldView extends SimpleView {
private JTextField value_field_ = new JTextField();
public SimpleTextFieldView(SimpleModel model) {
...
widget_ = new JPanel(new BorderLayout());
...
widget_.add(value_field_, BorderLayout.SOUTH);
}
public void updateView() {
value_field_.setText("" + model_.getValue());
}
}
Source code
MVC: An example with Observer pattern (7)
public class SimpleSliderView extends SimpleView {
private JSlider value_slider_ = new JSlider();
public SimpleSliderView(SimpleModel model) {
...
widget_ = new JPanel(new BorderLayout());
...
widget_.add(value_slider_, BorderLayout.SOUTH);
}
public void updateView() {
value_slider_.setValue(model_.getValue());
}
}
Source code
MVC: An example with Observer pattern (8)
- Controller
- Java Event System follows already MVC, i.e., it is the controller
- The event capturer forwards a captured event (e.g. a mouse click) to the event dispatcher
- The event dispatcher manages a mapping of events to event listeners
- The event dispatcher finds the proper listener and invokes its actionPerformed() method
- We need only to write listeners, register them with GUI widgets and implement action() methods
MVC: An example with Observer pattern (9)
final public class SimpleTextFieldView extends SimpleView {
public SimpleTextFieldView(SimpleModel model) {
...
value_field_.addActionListener(new TextFieldControllerAction());
...
}
class TextFieldControllerAction implements ActionListener {
public void actionPerformed(ActionEvent event) {
model_.setValue(Integer.parseInt(value_field_.getText()));
}
}
}
Source code
MVC: An example with Observer pattern (10)
public class SimpleSliderView extends SimpleView {
public SimpleSliderView(SimpleModel model) {
...
value_slider_.addChangeListener(new SliderControllerAction());
...
}
class SliderControllerAction implements ChangeListener {
public void stateChanged(ChangeEvent event) {
model_.setValue(value_slider_.getValue());
}
}
}
Source code
MVC: An example with Observer pattern (11)
public static void main(String[] args) {
SimpleModel model = new SimpleModel();
SimpleView view = new SimpleTextFieldView(model);
...
view = new SimpleSliderView(model);
...
model.setValue(12);
}
Source code
Complete source code
MVC Variations and Derivatives
- A number of further developments od the MVC pattern
- Model-View-Presenter
- Presentation-Abstraction-Control
Model-View-Presenter (1)
Model-View-Presenter (2)
- The Model refers to the data and business functionality of the application
- Selections are components which specify what portion of the data within the Model is to be operated upon
- Commands are components which define the operations which can be performed on the data
Model-View-Presenter (3)
- The View is the visual representation of the Model and is comprised of the screens and widgets used within an application
- Interactors are components which address how user events are mapped onto operations performed on the Model
- The Presenter is a component which orchestrates the overall interaction of the other components within the application
Model-View-Presenter (4)
- Actually, model-view-presenter is how a typical GUI application is built today
- Only selections and commands are separate components
- In a typical system selections and commands are defined through interfaces - such as DAO interfaces
Presentation-Abstraction-Control (1)
- It is a hierarchical variation of MVC
- E.g. there is a hierarchy of sub-systems where each sub-system follows MVC pattern
- The links between sub-systems model associations within an application, e.g. similar to links on the Web
Presentation-Abstraction-Control (2)
Presentation-Abstraction-Control (3)
- The Presentation is the visual representation of a particular abstraction within the application
- The Abstraction is the business domain functionality within the application, i.e. it is the model
- The Control is a component which maintains consistency between the abstractions within the system and their presentation to the user in addition to communicating with other Controls within the system
MVC on the server side (1)
- The server recieves different HTTP requests
- Requests can include different parameters submitted by the user
- On the basis of these parameters the server produces the response
- The server can dispatch the request to different handlers (actions)
- The server needs a registry of mappings of parameters onto actions
- The server, registry, dispatcher and actions are the Controller
MVC on the server side (2)
- The Model is accessed from the actions
- It is data and behaviour encapsulated within objects
- Each action is associated with a View
- When the action finishes the Controller invokes the View
- The View accesses the Model, retrieves (!) the data and present it
- The registry includes also associations between actions and views
MVC on the server side (3)
- In terms of MVP
- Registry contains interactors, i.e. mapping of user parameters onto actions
- Dispatcher is the presenter that controls the workflow
- Actions interact with commands and selectors
- Commands and selectors might be model interfaces or special objects that manipulate the model
MVC on the server side (4)
- In terms of PAC
- Each sub-system such as user management, administration, application logic is modeled by a MVC
- There are always links between sub-systems
- Administration tool is linked with user management module
- Data management module is linked with user management module
Struts - Java-based MVC Web App Framework (1)
Struts - Java-based MVC Web App Framework (1)
Struts - Java-based MVC Web App Framework (2)
- Download
- You can download either binaries or sources
- In the installation included: struts-blank.war
- You can use it for a quick start with Struts
- Only edit struts-config.xml and define your own actions
- Everything else is in place
Struts - Java-based MVC Web App Framework (3)
- Defining actions in struts-config.xml has a number of steps
- Defining a URL pattern for that action (pattern + .do)
- Defining a so-called ActionForm which encapsulates the user parameters
- There is a special JavaBean class that extends ActionForm class
- This class provides getters and setters for the parameters (same names)
- Defining a number of forwards to JSP pages to present the results
Struts - Java-based MVC Web App Framework (4)
<action-mappings>
...
<action
path="/search"
type="edu.iicm.publication.struts.SearchAction"
name="search_form"
scope="request"
validate="false"
input="/search.jsp">
<forward name="html" path="/search_results.jsp"/>
<forward name="bibtex" path="/search_export.jsp"/>
<forward name="rdf" path="/search_export.jsp"/>
</action>
...
</action-mappings>
Struts - Java-based MVC Web App Framework (5)
- If validate set to true then you can validate that the user parameters have the proper values
- Need to implement the validate() method inside your ActionForm subclass
- If validation fails
- The user is redirected to JSP specified in the input attribute
Struts - Java-based MVC Web App Framework (6)
- Name parameter refers to the ActionForm subclass
<form-beans>
...
<form-bean
name="search_form"
type="edu.iicm.publication.struts.SearchForm"/>
...
</form-beans>
Struts - Java-based MVC Web App Framework (7)
- Additionally, Java classes need to be implemented
- ActionForm subclass encapsulating parameters
- A subclass of the Action class which manipulates the Model objects
- Here you also decide to which JSP page to forward
- Finally, a number of JSP pages to present the results
Struts - An Example (1)
- Web-based database of scientific publications
- Used for managing of personal publication databases
- Retrieving of publications in different formats
- Searching for specific publications
- Type, year, title keywords
Struts - An Example (2)
- A special user as administrator
- Can add authors
- Can add publications
- Delete, update!
- Importing publications in different formats
Struts - An Example (3)
- Managing of publications
- Each publication has
- One or more authors
- Title
- Year of publishing
- Optionally URL
- Type (depends on format)
Struts - An Example (4)
- BibteX format http://www.din1505.informationskompetenz.net/
- Types such as Article, Conference, Book, etc
- Depending on type different additional attributes
- Article has a journal
- Book has a publisher, etc.
- BibteX format mapped onto a relational database (e.g., a number of relations)
Struts - An Example (5)
- Here we just want to investigate the Struts part of the example
- Search form, submitting queries
- Results in different formats
- Adimistration interface
- Registering, validating inputs, etc.
Struts - An Example (6)
- Right now we have the Model
- The Model includes classes for publications
- The Model and the DM are separated
- The lecture on O/R mapping will show how this is done
- The Model
Struts - An Example (7)
...
<action
path="/search"
type="edu.iicm.publication.struts.SearchAction"
name="search_form"
scope="request"
validate="false"
input="/search.jsp">
<forward name="html" path="/search_results.jsp"/>
<forward name="bibtex" path="/search_export.jsp"/>
<forward name="rdf" path="/search_export.jsp"/>
</action>
...
Struts - An Example (8)
<form-beans>
...
<form-bean
name="search_form"
type="edu.iicm.publication.struts.SearchForm"/>
...
</form-beans>
SearchForm bean
Struts - An Example (9)
public final class SearchAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
String type = ((SearchForm) form).getType();
...
String format = ((SearchForm) form).getFormat();
Struts - An Example (10)
...
Iterator pubs = dao.readAllPubs(type, year, title);
while (pubs.hasNext()) {
Publication pub = (Publication) pubs.next();
...
}
String result = new String(buffer);
request.setAttribute("result", result);
return mapping.findForward(format);
}
}
SearchAction
Struts - An Example (11)
<%@ include file="/jsp_layout/header.jsp" %>
<h2 class="hrthinbox">
All Publications
</h2>
<ul>
<%= request.getAttribute("result").toString() %>
</ul>
<div>
<a href = "search.jsp">Search again</a>
</div>
<%@ include file="/jsp_layout/footer.jsp" %>
Complete view
Struts - An Example (12)
- The example
- Search functionality
- You can select different criteria
- You can select different output formats
Struts - An Example (13)
- To have different output formats we use Visitor pattern
- Publication is an abstract class with an abstract write method
- Subclasses (Article, Book, ...) invoke an abstract method from an abstract Visitor
- They pass the reference to itself to the visitor
- Subclasses of Visitor implement the method
- Write out the proper format
Struts - An Example (14)
- New format - new Visitor
- Creation of Visitor with Abstract Factory
- Allows you to use the same code to write out HTML, BibteX, ...
Source code
Struts - An Example (15)
- Administration functionality
- Adding, deleting, updating, importing publications
- User management
- The user needs to log-in
- The user info need to be always available
- The user info should be used to check the rights
Struts - An Example (16)
- Session management
- Inserting a publication requires a number of steps
- Select a number of persons that are involved in the publication
- Select the type of the publication
- Enter the publication data (depends on the type)
Struts - An Example (17)
- Session management (continued)
- Each step is a separate HTTP request
- We need to manage the data over a number of HTTP requests
- The data is disparate (e.g., persons, pub type, etc.)
- We need special Java objects that encapsulate the needed info
Struts - An Example (18)
- HTML form validation
- At different steps different forms
- Different forms for different publication types
- A special login form
- Apply form bean validation provided by Struts
Struts - An Example (19)
- User management
- Login with a special login form
- Logout
- User information should be available for all administration actions
- Store it in the session object
Struts - An Example (20)
public final class User {
private String username_;
private String password_;
public User(String username, String password) {
setUsername(username);
setPassword(username);
}
...
}
Struts - An Example (21)
public final class User {
...
public void setPassword(String password) {
if((password == null) || (password.length() == 0)) {
throw new IllegalArgumentException(...);
}
password_ = password;
}
...
}
Source code
Struts - An Example (22)
<action
path="/login"
type="edu.iicm.publication.struts.LoginAction"
name="login_form"
scope="request"
validate="true"
input="/login.jsp">
<forward name="success" path="/manage.jsp"/>
<forward name="failure" path="/login.jsp"/>
</action>
Struts - An Example (23)
...
<form-bean
name="login_form"
type="edu.iicm.publication.struts.LoginForm"/>
...
Struts - An Example (24)
public final class LoginForm extends ActionForm {
private String username_ = null;
private String password_ = null;
...
public String getPassword() {
return password_;
}
public void setPassword(String password) {
password_ = password;
}
...
}
Struts - An Example (25)
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if((username_ == null) || (username_.length() == 0)) {
errors.add("username",
new ActionMessage("errors.username.required"));
}
...
return errors;
}
Source code
Struts - An Example (26)
- Error messages handling
- All messages have keys, e.g. errors.password.required
...
errors.username.required=Please enter your username!
errors.password.required=Please provide your password!
...
All keys and values stored in a special file
Struts - An Example (27)
- Login Action
- Reads username and password from the LoginForm
- Everything should be available since we have validation
- Compares username and password with a user database
- If authentication is OK creates and stores a User object
Struts - An Example (28)
- User Database
- Encapsulated as a Java object
- Public interface provides a single method: checkUsername()
- A particular implementation manages usernames and passwords
- In an XML file, a database, memory, etc
Struts - An Example (29)
- Very simple solution in the example
- Hardcoded in a hash table
public final class UserDatabase {
private HashMap users_;
...
private void init() {
users_ = new HashMap();
users_.put("dhelic", "dhelic");
}
...
}
Struts - An Example (30)
public final class UserDatabase {
...
public boolean checkUser(String username, String password) {
String db_password = (String) users_.get(username);
if(db_password == null) {
return false;
}
if(db_password.equals(password)) {
return true;
} else {
return false;
}
...
}
Struts - An Example (31)
- We need very often a UserDatabase object
- Each time a user wants to log in
- We can use a shared single instance of the UserDatabase class
- More efficient (e.g. created and loaded only once)
- More secure because nobody can create another instance
Struts - An Example (32)
- Singleton design pattern
- Managing and enforcing a single shared instance of a class
public final class UserDatabase {
private static UserDatabase instance_ = null;
...
public static UserDatabase getUserDatabase() {
if(instance_ == null) {
instance_ = new UserDatabase();
}
return instance_;
}
...
}
Struts - An Example (33)
- How to enforce that nobody creates another instance
- Declare the constructor as private
public final class UserDatabase {
...
private UserDatabase() {
init();
}
...
}
Source code
Struts - An Example (34)
public final class LoginAction extends BaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
String username = ((LoginForm) form).getUsername();
String password = ((LoginForm) form).getPassword();
ActionMessages errors = new ActionMessages();
if(!UserDatabase.getUserDatabase().checkUser(username, password)) {
errors.add(ActionErrors.GLOBAL_MESSAGE,
new ActionMessage("errors.authentication.failed"));
}
...
}
Struts - An Example (35)
public final class LoginAction extends BaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
...
if(!errors.isEmpty()) {
saveErrors(request, errors);
return mapping.findForward(Constants.FAILURE);
}
...
}
Struts - An Example (36)
public final class LoginAction extends BaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
...
User user = new User(username, password);
HttpSession session = request.getSession();
session.setAttribute(Constants.USER_KEY, user);
return mapping.findForward(Constants.SUCCESS);
}
...
}
Source code
Struts - An Example (37)
- What is BaseAction?
- It is always good to create an abstract BaseAction as a subclass of Struts action
- Declare an abstract execute() method
public abstract class BaseAction extends Action {
...
public abstract ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response);
...
}
Struts - An Example (38)
- Advantages of an abstract base action
- You can implement a number of common methods here
- You can use these methods within all subclasses
- User management as example
- All management actions need to check if user is authenticated
Struts - An Example (39)
public abstract class BaseAction extends Action {
protected boolean isUserAuthenticated(HttpServletRequest request) {
HttpSession session = request.getSession();
...
User user = (User) session.getAttribute(Constants.USER_KEY);
if(user == null) {
return false;
}
return true;
}
}
Source code
Struts - An Example (40)
...
<action
path="/logout"
type="edu.iicm.publication.struts.LogoutAction">
<forward name="success" path="/manage.jsp"/>
</action>
...
Struts - An Example (41)
- The action removes the user object and invalidates the session
public final class LogoutAction extends BaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
session.removeAttribute(Constants.USER_KEY);
session.invalidate();
return mapping.findForward(Constants.SUCCESS);
}
}
Ruby on Rails (1)
- Ruby is a pure object-oriented programming language
- http://www.ruby-lang.org/en/
- Pure means everything is an object, e.g. the number 1 is an instance of class Fixnum
- Interpreted scripting language
- Dynamically, weakly typed
- Single inheritance, but can be extended with so-called modules (similar to Java interfaces)
- Rich text processing functionality (similar to Perl)
Ruby on Rails (2)
- Rails is open source Web application framework
- http://www.rubyonrails.org/
- Supports development of database-backed application
- User-oriented Web database applications
- Follows MVC architecture and design pattern
Ruby on Rails (3)
- Three main guiding principles
- Model-driven (domain-driven) development
- You start with a data model and add the functionality, controllers, views on top of it
- Convention over configuration
- Set of naming conventions (similar to JavaBeans but more in depth)
- Less software, i.e., less code
- Generating default code that you adjust to fit your needs
Ruby on Rails (4)
- Domain-driven development
- Based on an ORM framework called ActiveRecord
- http://wiki.rubyonrails.com/rails/pages/ActiveRecord
- ActiveRecord is a generic ORM framework
- Similar to Hibernate
- Uses a naming convention to provide the default mapping
- You can adjust the default mapping if you need to
Ruby on Rails (5)
- ActiveRecord naming convention
- Names of classes and tables
- Give names to your classes as English singular, and to your tables as English plural
- Start the name of the class with an upper case, all other letters are lower case (Student)
- Table name is all lower case (students)
Ruby on Rails (6)
class Student < ActiveRecord::Base
end
create table students (
id int not null auto_increment,
name varchar(80),
study_field varchar(10),
primary key(id)
);
Ruby on Rails (7)
- Names of the table columns and instance variables
- Map 1-to-1, i.e., student.name maps to name column in students
- Primary key must be named id in the table
- Immediatelly you can use all methods from ActiveRecord
@students = Student.find_all
@student = Student.new
Ruby on Rails (8)
- Internally, ActiveRecord uses a single table to map the whole class hierarchy
- To map associations a simple domain language-like set of macros is used
Ruby on Rails (9)
class Student < ActiveRecord::Base
has_and_belongs_to_many :courses
end
- Connects two classes via an associative table (many-to-many relation)
- The name of the table: courses_students
- The names of foreign keys: course_id, student_id
Ruby on Rails (10)
- Convention over configuration
- A lot of examples in ActiveRecord
- Further examples in controller module of MVC
- Controllers are modules that handle user requests
- Convention on mapping of URLs onto methods in controllers
- Much easier than Struts configuration
Ruby on Rails (11)
class TestController < ApplicationController
def index
render_text "Wow, that was easy"
end
def hello
render_text "Hello World"
end
end
Ruby on Rails (12)
- Whenever you have a model class, e.g., Student class you can use a so-called CRUD scaffold
- create, read, update, delete methods
- These methods are provided by the ActiveRecord
class StudentController < ApplicationController
scaffold :student
end
Ruby on Rails (14)
- By scaffolding you also get default views
- However, you can adjust them
- For a particular controller method, e.g., show() you need to create show.rhtml
- Another naming convention
Ruby on Rails - Example (1)
- Courses and students registered for courses
- Two entities: Course and Student
- Many-to-many relation between Course and Student
- One student might register for a number of courses
- For each course there is a number of registered students
Ruby on Rails - Example (2)
- First step with Rails: Create database (MySQL)
- Follow the naming convention
create table courses (
id int not null auto_increment,
title varchar(200),
url varchar(200),
description text,
primary key(id)
);
Ruby on Rails - Example (3)
create table students (
id int not null auto_increment,
name varchar(80),
study_field varchar(10),
primary key(id)
);
create table courses_students (
course_id int not null,
student_id int not null,
primary key(course_id, student_id)
);
Ruby on Rails - Example (4)
- Second step with Rails: Generate app skeleton
- Invoke: rails courses
- You will get a directory structure:
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
vendor/
Ruby on Rails - Example (5)
- Within app directory you get something like:
app/
controllers/
helpers/
models/
views/
- Edit config/database.yml
- Start the app, invoke: ruby script/server
Ruby on Rails - Example (6)
- Third step: generate model and controller
- Invoke: ruby script/generate model Course
- Invoke: ruby script/generate model Student
- Invoke: ruby script/generate controller Course
- Invoke: ruby script/generate controller Student
Ruby on Rails - Example (7)
- Use the scaffold (the generated default controller and views)
class CourseController < ApplicationController
scaffold :course
end
class StudentController < ApplicationController
scaffold :student
end
- Fourth step: Work (!) and adjust the app!
Ruby on Rails - Example (8)
- Adjusting the app
- Create alternative views
- Update the method in controller, e.g. the show method
- Create the show.rhtml in views and adjust it
Ruby on Rails - Example (9)
<p><b>Title</b><br>
<%= @course.title %>
</p>
<p><b>URL</b><br>
<%= link_to @course.url, @course.url %>
</p>
<p><b>Description</b><br>
<%= @course.description %>
</p>
Ruby on Rails - Example (10)
- Implement the association
class Student < ActiveRecord::Base
has_and_belongs_to_many :course
end
Ruby on Rails - Example (11)
- Adjust edit.rhtml and update method in controller
<% for @course in @courses %>
<% if @student.courses.include? @course %>
<%= @course.title %> :
<input type="checkbox" name="<%= @course.title %>"
value="0" checked="checked"/><br />
<% else %>
<%= @course.title %> :
<input type="checkbox" name="<%= @course.title %>"
value="0"/><br />
<% end %>
<% end %>
Ruby on Rails - Example (12)
def update
@courses = Course.find_all
@student = Student.find(@params[:id])
if @student.update_attributes(params[:student])
@student.courses.clear
for course in @courses
if (@params[course.title])
@student.courses<<(course)
end
...
Example
Ruby on Rails: Advanced Features
- Defining layouts (headers, footers, ...)
- Modules for standard functionality, e.g., authentication
- Caching
- Validation and callbacks
- Transactions
- Testing