@ -0,0 +1,255 @@
|
|||||||
|
# TWEET_R
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Yep.
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## Walkthrough: Rails R app - R stands for Read (the 'R' in CRUD)
|
||||||
|
|
||||||
|
|
||||||
|
We will be making a new Rails R app with a single model called `tweet`, with routes, controllers, and views.
|
||||||
|
|
||||||
|
This app will use a database, `postgresql`. You will be doing migrations and filling out a schema. Don't worry about what the word 'migration' means in this context, or what it does. Just follow the instructions and all should become clear.
|
||||||
|
|
||||||
|
We will be making much of this manually without scaffolds or generators for our controllers and models. This way, you will develop some muscle memory and a greater understanding of each step of the process. Having said that, this app goes over only the most basic stuff that you need to know to display an index and show route, and nothing more. Once you have these fundamentals under your belt we can implement more advanced stuff later on.
|
||||||
|
|
||||||
|
Rails is a framework that favors **convention** over **configuration**, so it is important to name your folders, files, and classes with the correct combination of upper/lowercase letters and plural/singular business.
|
||||||
|
|
||||||
|
|
||||||
|
### 1. LET THERE BE LIGHT
|
||||||
|
1. Make a new Rails app called `tweeter`. Set `postgresql` as the database. Here is the command:
|
||||||
|
`rails new tweeter --database=postgresql`
|
||||||
|
|
||||||
|
2. **Go into your new directory**
|
||||||
|
|
||||||
|
### 2. DATABASE AND MIGRATIONS
|
||||||
|
|
||||||
|
#####Let's walk through how to set up your database. This involves:
|
||||||
|
```
|
||||||
|
1. Creating the database
|
||||||
|
2. Setting up a migration
|
||||||
|
3. Filling in a schema
|
||||||
|
4. Running the migration
|
||||||
|
```
|
||||||
|
|
||||||
|
- Create your database in your project directory by running this command:
|
||||||
|
`rake db:create`
|
||||||
|
|
||||||
|
```
|
||||||
|
Rake is a helpful task manager in Rails that can do lots of things for us, including creating, migrating and seeding our database.
|
||||||
|
```
|
||||||
|
|
||||||
|
- Test that the db has been created by typing `rails dbconsole`. This opens a console for our database, in which we can type raw SQL commands. For now, just check that it opens, then quit the console with `\q`.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
CONGRATULATIONS. You have successfully set up a database for Rails.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#####Now it's time for Migrations
|
||||||
|
|
||||||
|
A migration is a proposed change to the database. You set up a migration, enter your changes, then run the migration to lock in the changes. Rails then keeps a record of all migrations so that you can see the full history of your database.
|
||||||
|
|
||||||
|
- **Make a new migration**
|
||||||
|
Let's set up a migration. In terminal, inside your project folder, type: `rails g migration CreateTweets`. The `g` is short for generate. `Create` is a Rails keyword helper for making migration files for your database. `Tweets` must be *plural* and have a *capital T*. There is no space between Create and Tweets. It's `CreateTweets`.
|
||||||
|
|
||||||
|
- In your text editor project folder, look in the `db` folder. The migration command created another folder `migrate`, and you should see a migration file in there that looks like a bunch of numbers:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Click on the migration file, and you should see some code like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
In here, you will add your model's columns and datatypes, as if making a `schema`.
|
||||||
|
|
||||||
|
A tweet should have an author, a title, content, and timestamps. Don't worry about why the syntax is the way it is, for now, just adapt your migration file to look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
class CreateTweets < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :tweets do |t|
|
||||||
|
t.string "title"
|
||||||
|
t.text "content"
|
||||||
|
t.string "author"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
- Now, run the migration. In terminal, in your project folder as usual,
|
||||||
|
enter `rake db:migrate`. We're using rake again to help us with our database. In this case, it's running our migrations. Thanks, rake.
|
||||||
|
|
||||||
|
What does the migration do? It adds the schema to our database, and also makes us a `schema.rb` file in the db folder. We never touch the schema.rb file.
|
||||||
|
|
||||||
|
**IMPORTANT: Once a migration has run, you never edit your migration or schema file. The migration files are there forever as records of all your migrations. To edit a migration, you make a new migration to act on the previous one. To alter your schema, you also make a new migration.**
|
||||||
|
|
||||||
|
|
||||||
|
- Test that your db has been schema-fied by going into the console and typing `rails dbconsole`. Perform a `SELECT * FROM tweets` to test that your db has the correct columns, then quit the dbconsole with `\q`.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
CONGRATULATIONS. You have successfully created and run a migration.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 3. MODELS
|
||||||
|
|
||||||
|
This is "relatively straightforward". :P
|
||||||
|
|
||||||
|
1. **Create a model.** In the app/models folder, NOT in concerns, create a file called `tweet.rb`. It has to be **singular lower case** or it will break.
|
||||||
|
|
||||||
|
2. Inside `tweet.rb` make a class called Tweet **singular, uppcase T** that inherits from ActiveRecord::Base.
|
||||||
|
|
||||||
|
```
|
||||||
|
class Tweet < ActiveRecord::Base
|
||||||
|
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
That's it!
|
||||||
|
|
||||||
|
|
||||||
|
### 4. SEED
|
||||||
|
- Seed your database with data for your models: two Tweet entries. In the `db` folder there is a file called `seeds.rb` wherein you can make seeds like the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
Tweet.create({
|
||||||
|
title: "Just found this",
|
||||||
|
content: "the square of the hypotenuse is equal to the sum of the squares of the other two sides",
|
||||||
|
author: "Pythagoras570"
|
||||||
|
})
|
||||||
|
|
||||||
|
Tweet.create({
|
||||||
|
title: "I'm walkin' here",
|
||||||
|
content: "Hey, I'm walkin' here!",
|
||||||
|
author: "Nicky62"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- To import your seed into your database, run `rake db:seed` in terminal.
|
||||||
|
|
||||||
|
- Test that your seed worked by going into `rails dbconsole`, performing a SELECT query, and then quit.
|
||||||
|
|
||||||
|
- Test your model by opening up Rails console. Rails console is where you can make Active Record queries. Open it with `rails console` or just `rails c`. Query all of your tweets with `Tweet.all`. Quit rails console with `exit`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 4. ROUTES
|
||||||
|
1. In config/routes.rb add `resources :tweets`.
|
||||||
|
Test your routes by typing `rake routes` in the console. You should get this:
|
||||||
|
|
||||||
|
```
|
||||||
|
Prefix Verb URI Pattern Controller#Action
|
||||||
|
tweets GET /tweets(.:format) tweets#index
|
||||||
|
POST /tweets(.:format) tweets#create
|
||||||
|
new_tweet GET /tweets/new(.:format) tweets#new
|
||||||
|
edit_tweet GET /tweets/:id/edit(.:format) tweets#edit
|
||||||
|
tweet GET /tweets/:id(.:format) tweets#show
|
||||||
|
PATCH /tweets/:id(.:format) tweets#update
|
||||||
|
PUT /tweets/:id(.:format) tweets#update
|
||||||
|
DELETE /tweets/:id(.:format) tweets#destroy
|
||||||
|
```
|
||||||
|
|
||||||
|
You can delete all the extraneous comments in `routes.rb`
|
||||||
|
|
||||||
|
|
||||||
|
### 5. CONTROLLER
|
||||||
|
1. In your app/controllers folder, manually create a new file
|
||||||
|
called `tweets_controller.rb`. Don't put it into the concerns folder. **The word tweets must be lowercase and plural or the app will break.**
|
||||||
|
|
||||||
|
2. Inside `tweets_controller.rb` make a new class called `TweetsController` that inherits from `ApplicationController`. **The word Tweets here must be plural with an uppercase T, and Controller must have an uppercase C**
|
||||||
|
|
||||||
|
3. Add the methods that correspond to your restful routes you'll be using: index and show.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*** Try running your app to see if it will break with `rails s`. The `s` is short for server. It won't show anything yet, but you should get it to where it won't break.***
|
||||||
|
|
||||||
|
|
||||||
|
### 6. VIEWS
|
||||||
|
|
||||||
|
1. In the app/views folder, make a folder for your tweets views. It should be called tweets **lowercase plural**.
|
||||||
|
|
||||||
|
2. In your views/tweets folder, start by making a view file called `index.html.erb`. This corresponds to your index method in your controller.
|
||||||
|
|
||||||
|
|
||||||
|
### 7. TEST
|
||||||
|
|
||||||
|
1. Make an instance variable in your tweets#index controller method. Set it to a string, such as `@test = "gidday mate"`. **Instance variable are accessible in the views**. Regular variables are not.
|
||||||
|
|
||||||
|
2. In your tweets view folder, in `index.html.erb`, write some erb that will display the instance variable: `<%=@test%>`
|
||||||
|
|
||||||
|
3. When you go to access the url `/tweets` in your browser (the tweets index), you should see the value of `@test` on your screen.
|
||||||
|
|
||||||
|
|
||||||
|
### 8. MVC
|
||||||
|
|
||||||
|
|
||||||
|
###### INDEX
|
||||||
|
The index route in your controller is a GET route and wants to send information to the page for a user to see. For the index route, in your controller file:
|
||||||
|
|
||||||
|
```
|
||||||
|
def index
|
||||||
|
@tweets = Tweet.all
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
`Tweet.all` queries your model for every tweet entry and sends back an array. We save this array into `@tweets`.
|
||||||
|
|
||||||
|
In our `index.html.erb` view, we can iterate over the `@tweets` array using Ruby, Let's use `.each` to display every individual tweet.
|
||||||
|
|
||||||
|
```
|
||||||
|
<% @tweets.each do |single_tweet| %>
|
||||||
|
<%= single_tweet.title %>
|
||||||
|
<%= single_tweet.author %>
|
||||||
|
<%= single_tweet.content %>
|
||||||
|
<% end %>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Test this out and keep working at it until you get each tweet displayed**
|
||||||
|
|
||||||
|
You can go ahead and make this legible on the page using html tags.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###### SHOW
|
||||||
|
|
||||||
|
```
|
||||||
|
def show
|
||||||
|
@tweet = Tweet.find(params[:id])
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9. ON YOUR OWN
|
||||||
|
|
||||||
|
1. Make a view for your show.
|
||||||
|
|
||||||
|
2. Make each tweet on your index page link to its corresponding show page.
|
||||||
|
|
||||||
|
3. Add a new Tweet with Active Record through rails console, `rails c`. See it appear in the view.
|
||||||
|
|
||||||
|
4. Edit a Tweet with Active Record through rails console. See that it changed in the view.
|
||||||
|
|
||||||
|
5. Delete a tweet with Active Record through rails console. See that it was deleted in the view.
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 162 KiB |
@ -0,0 +1,261 @@
|
|||||||
|
# NYC NEIGHBORHOOD APP - Rails
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Walkthrough: Rails CRUD app
|
||||||
|
|
||||||
|
|
||||||
|
We will be making a new Rails CRUD app with a single model called `neighborhood`, with routes, controllers, and views. We will be making much of this manually without scaffolds or generators for controllers and models. This way, you will develop some muscle memory and a greater understanding of each step of the process.
|
||||||
|
|
||||||
|
Rails is a framework that favors **convention** over **configuration**, so it is important to name your folders, files, and classes with the correct combination of upper/lowercase letters and plural/singular business.
|
||||||
|
|
||||||
|
|
||||||
|
### 1. INITIALIZE APP
|
||||||
|
1. Make a new Rails app
|
||||||
|
`rails new neighborhoods --database=postgresql`
|
||||||
|
|
||||||
|
2. **Go into your new directory**
|
||||||
|
|
||||||
|
3. Run `bundle install` to install all your gems
|
||||||
|
|
||||||
|
### 2. DATABASE AND MIGRATIONS
|
||||||
|
1. Create your database from the same directory
|
||||||
|
`rake db:create`
|
||||||
|
|
||||||
|
2. Test that the db has been created with `rails dbconsole`.
|
||||||
|
Then quit the console.
|
||||||
|
|
||||||
|
3. Make a new migration:
|
||||||
|
`rails g migration CreateNeighborhoods`. The g is short for generate, and Create is a rails keyword helper for making migration files for your database. `Neighborhoods` must be *plural* and have a *capital first letter*. There is no space between Create and Neighborhoods. It's `CreateNeighborhoods`.
|
||||||
|
|
||||||
|
4. In your sublime in your project folder, open up your migrate folder in your db folder, and you should see a migration file that looks like a bunch of numbers. You will add your model columns and datatypes into this file: A neighborhood should have a name, borough, description, population, and img_url. It should look like this when you are done with it:
|
||||||
|
|
||||||
|
```
|
||||||
|
def change
|
||||||
|
create_table :neighborhoods do |t|
|
||||||
|
t.string "name"
|
||||||
|
t.string "borough"
|
||||||
|
t.text "description"
|
||||||
|
t.string "population"
|
||||||
|
t.text "img_url"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Migrate your schema to your database *after* you have entered the information into your migration file. Run the migration with
|
||||||
|
`rake db:migrate`. This will create a `schema.rb` that you never touch.
|
||||||
|
|
||||||
|
**IMPORTANT: Once a migration has run, you never edit your migration or schema file. It is there forever as a record of all your migrations. To edit a migration, you make a new migration to act on the previous one**
|
||||||
|
|
||||||
|
Therefore, make sure all your info is correct the first time.
|
||||||
|
|
||||||
|
Test that your table has been made by going into the console and typing `rails dbconsole`. Perform a SELECT to test then quit the dbconsole.
|
||||||
|
|
||||||
|
|
||||||
|
### 3. MODELS
|
||||||
|
1. Create a model. In the app/models folder, create a file called `neighborhood.rb`. It has to be **singular lower case** or it will break.
|
||||||
|
|
||||||
|
2. Inside neighborhood.rb make a class called Neighborhood **singular, uppcase N** that inherits from ActiveRecord::Base
|
||||||
|
|
||||||
|
3. Seed your database with data for your models, two Neighborhood entries. In db/seeds.rb in your project folder, you can make seeds like the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
Neighborhood.create({
|
||||||
|
name: "Flatbush",
|
||||||
|
borough: "Brooklyn",
|
||||||
|
description: "Founded in 1651 by Dutch colonists, Flatbush consists of several subsections.",
|
||||||
|
population: "110,875",
|
||||||
|
img_url: "http://subwaynut.com/irt/flatbushn2/flatbushn215.jpg"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
4. To import your seed into your database, run `rake db:seed` in terminal.
|
||||||
|
|
||||||
|
5. Test that your seed worked by going into `rails dbconsole`, performing a SELECT query, and then quit.
|
||||||
|
|
||||||
|
6. Test your model by opening up Rails console `rails c`, and querying `Neighborhood.all`, then quit.
|
||||||
|
|
||||||
|
|
||||||
|
### 4. ROUTES
|
||||||
|
1. In config/routes.rb add `resources :neighborhoods`.
|
||||||
|
Test your routes by typing `rake routes` in the console. You should get this:
|
||||||
|
|
||||||
|
```
|
||||||
|
Prefix Verb URI Pattern Controller#Action
|
||||||
|
neighborhoods GET /neighborhoods(.:format) neighborhoods#index
|
||||||
|
POST /neighborhoods(.:format) neighborhoods#create
|
||||||
|
new_neighborhood GET /neighborhoods/new(.:format) neighborhoods#new
|
||||||
|
edit_neighborhood GET /neighborhoods/:id/edit(.:format) neighborhoods#edit
|
||||||
|
neighborhood GET /neighborhoods/:id(.:format) neighborhoods#show
|
||||||
|
PATCH /neighborhoods/:id(.:format) neighborhoods#update
|
||||||
|
PUT /neighborhoods/:id(.:format) neighborhoods#update
|
||||||
|
DELETE /neighborhoods/:id(.:format) neighborhoods#destroy
|
||||||
|
```
|
||||||
|
|
||||||
|
You can delete all the extraneous comments in routes.rb
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 5. CONTROLLER
|
||||||
|
1. In your app/controllers folder, manually create a new file
|
||||||
|
called `neighborhoods_controller`. **The word neighborhoods must be lowercase and plural or the app will break.**
|
||||||
|
|
||||||
|
2. Inside `neighborhoods_controller` make a new class called `NeighborhoodsController` that inherits from ApplicationController. **The word Neighborhoods must be plural with an uppercase first letter, and Controller must have an uppercase C**
|
||||||
|
|
||||||
|
3. Add the seven methods that correspond to your seven restful routes: index, create, new, edit, show, update, destroy. You don't need to put anything into these methods for now.
|
||||||
|
|
||||||
|
|
||||||
|
### 6. VIEWS
|
||||||
|
|
||||||
|
1. In the app/views folder, make a folder for your neighborhoods views. It should be called `neighborhoods` **lowercase plural**.
|
||||||
|
|
||||||
|
2. In your views/neighborhoods folder, start by making a view file called `index.html.erb`. This corresponds to your index method in your controller.
|
||||||
|
|
||||||
|
|
||||||
|
### 7. TEST: CONTROLLER -> VIEW
|
||||||
|
|
||||||
|
Make an instance variable in your neighborhoods#index controller method. Set it to a string, such as `@test = "America Burger USA 2015 github.com.biz.usa.patty"`.
|
||||||
|
|
||||||
|
In your neighborhoods view folder, in `index.html.erb`, write some erb that will display the instance variable: `<%=@test%>`
|
||||||
|
|
||||||
|
When you go to access the url `/neighborhoods` in your browser (your index url), you should see the value of `@test` on your screen.
|
||||||
|
|
||||||
|
|
||||||
|
### 8. COMPLETE YOUR CONTROLLER
|
||||||
|
|
||||||
|
Fill out your controller. Note that in the example below, variables below are named `@item` or `@items` or `Item`: your app will not have variables called `item`. You will probably want to use `@neighborhood` or `@neighborhoods` and query the `Neighborhood` model.
|
||||||
|
|
||||||
|
Note that we are using `strong params` here in `create` and `update` by referring to a private method the restricts the params we are going to make and/or update.
|
||||||
|
|
||||||
|
Your `create`, `update` and `destroy` routes will need redirects. These redirects correspond to the prefixes in your `rake routes` with a `_path` appended.
|
||||||
|
|
||||||
|
Example using an Item model instead of a Neighborhood model:
|
||||||
|
|
||||||
|
```
|
||||||
|
def index
|
||||||
|
@items = Item.all
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@item = Item.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@item = Item.create(item_params)
|
||||||
|
redirect_to items_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@item = Item.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@item = Item.find(params[:id])
|
||||||
|
@item.update_attributes(item_params)
|
||||||
|
thom waz here-- don't copy-paste code
|
||||||
|
redirect_to items_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
@item = Item.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@item = Item.find(params[:id])
|
||||||
|
@item.destroy
|
||||||
|
redirect_to items_path
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def item_params
|
||||||
|
params.require(:item).permit(:gossipgirl, :rupaulsdragrace, :mrrobot)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 9. COMPLETE YOUR VIEWS
|
||||||
|
|
||||||
|
All of your GET routes will need views. `index`, `show`, `edit`, and `new` are GET routes. Complete the views for `index` and `show`.
|
||||||
|
|
||||||
|
- Each item in your `index` should link to that item's `show` page.
|
||||||
|
|
||||||
|
- Make forms inside the views that require forms: `edit` and `new`.
|
||||||
|
|
||||||
|
- An item's `show` page should have a link to `delete` that item. Put it in `show`.
|
||||||
|
|
||||||
|
- Also on the `show` page, provide a link to `edit` that item.
|
||||||
|
|
||||||
|
This tutorial gives complete, basic examples of using views, as well as some other useful stuff: <a href="http://tutorials.jumpstartlab.com/projects/blogger.html">Blogger2 Tutorial</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 10. MAKE STATIC PAGES
|
||||||
|
|
||||||
|
|
||||||
|
- Make some extra, static pages for your Rails app. How would you make an `about` or `contact` page?
|
||||||
|
|
||||||
|
- Add routing in your `routes.rb`, to tell Rails where to look when certain routes are hit:
|
||||||
|
|
||||||
|
```
|
||||||
|
get '/about', to: 'static#about'
|
||||||
|
get '/contact', to: 'static#contact'
|
||||||
|
```
|
||||||
|
|
||||||
|
- In this case, we're telling Rails to look in a controller called 'static', and further to look at the actions called `about` and `contact`. Make a controller, call it `static_controller` to handle these static pages. This controller requires no models, migrations, etc. It's just a controller.
|
||||||
|
|
||||||
|
- The actions in the controller correspond to the pages themselves. `def about`, and `def contact`. These correspond to views that you will make in a `static` folder or `pages` folder in your `views`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 11. EXTRAS
|
||||||
|
|
||||||
|
- Set your root to the index.
|
||||||
|
|
||||||
|
- Use partials to render your forms.
|
||||||
|
|
||||||
|
- Do some very basic styling on your app with css stylesheet in the assets folder.
|
||||||
|
|
||||||
|
- Look into a CSS framework like `Bootstrap`, `Skeleton`, `Pure`, or `Foundation`, and implement styling on your pages using one of those.
|
||||||
|
|
||||||
|
- Add data validation to your model
|
||||||
|
|
||||||
|
- Try out giving your app some JavaScript functionality through the assets folder.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 12. FIFO / BONUS
|
||||||
|
#### Make a second model with a one-to-many relationship
|
||||||
|
|
||||||
|
Let's expand our neighborhoods beyond NYC, and make a new model called City. A city **has many** neighborhoods. A neighborhood **belongs to** a city.
|
||||||
|
|
||||||
|
- Create a migration files for cities.
|
||||||
|
|
||||||
|
- In your neighborhood.rb model file, specify this relationship with `belongs_to: cities`
|
||||||
|
- In your city.rb model file, specify this relationship with `has_many: neighborhoods`
|
||||||
|
|
||||||
|
- The neighborhood table will need a column for the foreign key. Run a migration that will add a `t.belongs_to :city` column in your neighborhoods table. This is the foreign key.
|
||||||
|
|
||||||
|
- Get it all working such that when you add a new Neighborhood, you specify the city, and can then see an index of cities, wherein you can see each city's neighborhoods.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,173 @@
|
|||||||
|
# Books_app
|
||||||
|
|
||||||
|
- Create a rails app called `books_app`
|
||||||
|
- Create a books controller
|
||||||
|
- Populate it with the following...
|
||||||
|
```
|
||||||
|
class BooksController < ApplicationController
|
||||||
|
|
||||||
|
def index
|
||||||
|
# Fake DB ORM call
|
||||||
|
puts "============="
|
||||||
|
@all_books = $BOOKS
|
||||||
|
p @all_books
|
||||||
|
puts "============="
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
# Get the id via params
|
||||||
|
id = params[:id].to_i
|
||||||
|
puts "============="
|
||||||
|
puts id
|
||||||
|
puts id.class
|
||||||
|
puts "============="
|
||||||
|
|
||||||
|
@book = {}
|
||||||
|
$BOOKS.each do |book|
|
||||||
|
if book[:id] === id
|
||||||
|
@book = book
|
||||||
|
puts "============="
|
||||||
|
puts "book found"
|
||||||
|
puts "============="
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remember, just putting the final variable makes it implicitly return
|
||||||
|
@book
|
||||||
|
|
||||||
|
# More statements to test
|
||||||
|
puts "================"
|
||||||
|
p @book
|
||||||
|
puts "================"
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@book = Book.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
name = book_params[:title]
|
||||||
|
nickname = book_params[:author]
|
||||||
|
new_id = $BOOKS.length + 1
|
||||||
|
|
||||||
|
$BOOKS << { id: new_id, title: title, author: author}
|
||||||
|
|
||||||
|
redirect_to :root
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
id = params[:id].to_i
|
||||||
|
puts "============="
|
||||||
|
puts id
|
||||||
|
puts id.class
|
||||||
|
puts "============="
|
||||||
|
|
||||||
|
find_book = {}
|
||||||
|
$BOOKS.each do |book|
|
||||||
|
if book[:id] === id
|
||||||
|
find_book = book
|
||||||
|
puts "============="
|
||||||
|
puts "book found"
|
||||||
|
puts "============="
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@book_teacher = Book.new(find_book)
|
||||||
|
|
||||||
|
@book = @existing_book
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
id = params[:id].to_i
|
||||||
|
new_title = book_params[:title]
|
||||||
|
new_author = book_params[:author]
|
||||||
|
|
||||||
|
$BOOKS.each do |book|
|
||||||
|
if book[:id] == id
|
||||||
|
book[:title] = new_title
|
||||||
|
book[:authoer] = new_author
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_to :root
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
id = params[:id].to_i
|
||||||
|
$BOOKS.each do |book|
|
||||||
|
if book[:id] == id
|
||||||
|
$BOOKS.delete(book)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_to :root
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def book_params
|
||||||
|
params.require(:book).permit(:title, :author)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
```
|
||||||
|
- Add dummy book data. Inside configs->initializers
|
||||||
|
- create `books.rb`
|
||||||
|
- populate it with the following...
|
||||||
|
```
|
||||||
|
$BOOKS = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "The Book of Awesomesauce",
|
||||||
|
author: "Joe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "The Book of coolness",
|
||||||
|
author: "Matt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "Death is yummy",
|
||||||
|
author: "Thom"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
- Create your routes using resources on books.
|
||||||
|
- Create a tableless model so that we can use dummy data
|
||||||
|
- Inside app/models
|
||||||
|
- create `books.rb`
|
||||||
|
- populate it with the following...
|
||||||
|
```
|
||||||
|
class Book
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
attr_accessor :title, :author, :id
|
||||||
|
validates :title, :author, presence: true
|
||||||
|
end
|
||||||
|
```
|
||||||
|
- Build out views
|
||||||
|
- Create a folder for books
|
||||||
|
- Create the corresponding html.erb files for the following
|
||||||
|
- index.html.erb
|
||||||
|
- edit.html.erb
|
||||||
|
- new.html.erb
|
||||||
|
- show.html.erb
|
||||||
|
- _form.html.erb
|
||||||
|
- Create links using the link_for helper to attach the user's experience to navigate the show and delete actions off the index page.
|
||||||
|
- Be sure to play with the path prefixing off the rake routes.
|
||||||
|
- Create a link to show for each book off the index page.
|
||||||
|
- Use the following to create the _form.html.erb
|
||||||
|
```
|
||||||
|
<%= form_for @book do |form| %>
|
||||||
|
Name: <%= form.text_field :title %><br>
|
||||||
|
Nickname: <%= form.text_field :author %><br>
|
||||||
|
<%= form.submit %>
|
||||||
|
<% end %>
|
||||||
|
```
|
||||||
|
- Use the `_form.html.erb` partial for the edit.html.erb and the new.html.erb
|
||||||
|
- Note that the edit form will continue to add a new instance of book, don't worry about this bug.
|
||||||
|
|
||||||
|
|
||||||
|
#### Rely on the various notes from today and the reference code as well as start looking up rails documentation and SO's.
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
# MEMORY LANE - Part 1
|
||||||
|
|
||||||
|
Remember all the morning exercises we did in Javascript? Let's revisit these exercises one-by-one. We already have an idea how to approach them having done them before, so let's try to solve them again while also translating them to Ruby.
|
||||||
|
|
||||||
|
### 1. EULER PROBLEM 1
|
||||||
|
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
|
||||||
|
|
||||||
|
Find the sum of all the multiples of 3 or 5 below 1000.
|
||||||
|
|
||||||
|
### 2. PALINDROME
|
||||||
|
Make a ruby method that returns true if a string is a palindrome, false if not. Make sure it returns the correct result for words with capital letters.
|
||||||
|
|
||||||
|
### 3. BUBBLE SORT
|
||||||
|
https://github.com/ga-students/WDI_NYC_Meeseeks/blob/master/unit_01/w02d04/morning_exercise/bubble_sort.md
|
||||||
|
|
||||||
|
### 4. PRIMES
|
||||||
|
https://github.com/ga-students/WDI_NYC_Meeseeks/blob/master/unit_01/w02d04/morning_exercise/primes.md
|
||||||
|
|
||||||
|
Check out Ruby's `Prime` class: http://ruby-doc.org/stdlib-1.9.3/libdoc/prime/rdoc/Prime.html
|
||||||
|
|
||||||
|
### 5. BONUS: RECURSIVE FACTORIAL
|
||||||
|
https://github.com/ga-students/WDI_NYC_Meeseeks/blob/master/unit_02/w04d04/morning_exercise/recursive_factorial.md
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
# EULER1
|
||||||
|
|
||||||
|
result = (1...10).select do |num|
|
||||||
|
num % 3 == 0 || num % 5 == 0
|
||||||
|
end.reduce(:+)
|
||||||
|
|
||||||
|
|
||||||
|
# PALINDROME
|
||||||
|
|
||||||
|
def palindrome(word)
|
||||||
|
word == word.downcase.reverse
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# BUBBLE SORT
|
||||||
|
|
||||||
|
def bubblesort(arr)
|
||||||
|
swap = true
|
||||||
|
while swap do
|
||||||
|
swap = false
|
||||||
|
(arr.length - 1).times do |i|
|
||||||
|
if arr[i] > arr[i + 1]
|
||||||
|
arr[i], arr[i + 1] = arr[i + 1], arr[i]
|
||||||
|
swap = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
arr
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# PRIMES
|
||||||
|
|
||||||
|
require 'prime'
|
||||||
|
|
||||||
|
def sum_primes(num)
|
||||||
|
sum = 0
|
||||||
|
Prime.each(num) do |n|
|
||||||
|
sum += n
|
||||||
|
end
|
||||||
|
sum
|
||||||
|
end
|
||||||
|
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
# MEMORY LANE - Part 2
|
||||||
|
|
||||||
|
Remember all the morning exercises we did in Javascript? Let's revisit these exercises one-by-one. We already have an idea how to approach them having done them before, so let's try to solve them again while also translating them to Ruby.
|
||||||
|
|
||||||
|
### 6. WORD FREQUENCY
|
||||||
|
https://github.com/ga-students/WDI_NYC_Meeseeks/blob/master/unit_02/w05d01/morning_exercise/word_frequency.md
|
||||||
|
|
||||||
|
### 7. 100 GOBLINS
|
||||||
|
NOTE: Using `for` loops is not really the Ruby way. Look up the following looping methods: `.times`, `.step`, and `.each_with_index`.
|
||||||
|
|
||||||
|
https://github.com/ga-students/WDI_NYC_Meeseeks/blob/master/unit_02/w05d03/morning_exercise/goblins.md
|
||||||
|
|
||||||
|
### 8. PANDIGITAL NUMBERS
|
||||||
|
https://github.com/ga-students/WDI_NYC_Meeseeks/blob/master/unit_02/w05d04/morning_exercise/pandigital_numbers.md
|
||||||
|
|
||||||
|
### 9. LUHN ALGORITHM
|
||||||
|
https://github.com/ga-students/WDI_NYC_Meeseeks/blob/master/unit_03/w08d01/morning_exercise/luhn_algorithm.md
|
||||||
|
|
||||||
|
### 10. CLOCK HANDS
|
||||||
|
https://github.com/ga-students/WDI_NYC_Meeseeks/blob/master/unit_03/w08d05/morning_exercise/clockhands.md
|
||||||
@ -0,0 +1,107 @@
|
|||||||
|
# BASIC RUBY REFRESHER
|
||||||
|
|
||||||
|
## Strings
|
||||||
|
|
||||||
|
Perform the following tasks using string methods:
|
||||||
|
|
||||||
|
1. Reverse the string, `"sarcophagus"`.
|
||||||
|
2. Return the substring, `"undulating"`, from the string, `"Are these artichokes undulating?"`.
|
||||||
|
3. Convert the string, `"90210"`, to an integer.
|
||||||
|
4. Capitalize the letter `"m"` in the string `"meeseeks"`.
|
||||||
|
5. Capitalize all of the letters in the string `"Capitalize all of the letters in the string"`.
|
||||||
|
|
||||||
|
|
||||||
|
## Arrays and Loops
|
||||||
|
|
||||||
|
##### NOTES
|
||||||
|
|
||||||
|
`.each` and `.map`
|
||||||
|
|
||||||
|
You can use `.each` as a basic loop for pushing values into arrays or sending out transforms without altering the original array. For example, given the following dataset:
|
||||||
|
|
||||||
|
```
|
||||||
|
arr1 = ["moops", "cherish the cabin"]
|
||||||
|
arr2 = []
|
||||||
|
```
|
||||||
|
|
||||||
|
`.each` for *pushing* into another array.
|
||||||
|
Note: `<<` is the same as `.push()`
|
||||||
|
|
||||||
|
```
|
||||||
|
arr1.each { |item| arr2 << item.upcase }
|
||||||
|
p arr2
|
||||||
|
|
||||||
|
=> ["MOOPS", "CHERISH THE CABIN"]
|
||||||
|
```
|
||||||
|
|
||||||
|
This is the expanded version using `do` and `end` instead of curlies:
|
||||||
|
|
||||||
|
```
|
||||||
|
arr1.each do |item|
|
||||||
|
arr2 << item.upcase
|
||||||
|
end
|
||||||
|
|
||||||
|
=> ["MOOPS", "CHERISH THE CABIN"]
|
||||||
|
```
|
||||||
|
|
||||||
|
`.map`, by contrast, returns a transform of the dataset:
|
||||||
|
|
||||||
|
```
|
||||||
|
new_set = arr1.map { |item| item.upcase }
|
||||||
|
p new_set
|
||||||
|
|
||||||
|
=> ["MOOPS, CHERISH THE CABIN"]
|
||||||
|
```
|
||||||
|
|
||||||
|
`.each` will not do a transform:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
new_set = arr1.each { |item| item.upcase }
|
||||||
|
p new_set
|
||||||
|
|
||||||
|
=> ["moops", "cherish the cabin"]
|
||||||
|
```
|
||||||
|
|
||||||
|
##### EXERCISE
|
||||||
|
|
||||||
|
Perform the following tasks using array methods (note: you might also need to use some string methods): Switch it up between `.map` and `.each` and any others you might find in the docs.
|
||||||
|
|
||||||
|
1. Given the array `numbers = [1, 3, 5, 7]`, use `map` to create a new array with each element of `numbers` multiplied by three. Do it once with `do .. end` and once with curlies.
|
||||||
|
|
||||||
|
2. Save a shuffled version of this array to a variable just to see how easy it is to do so.
|
||||||
|
|
||||||
|
3. Give the array `names = ["Joe, Matt, Thom"]` use `each` to iterate over each word and print it to the console with " is my friend and contemporary." appended. Do it once with `do .. end` and again with curlies.
|
||||||
|
|
||||||
|
4. Given the following array (of arrays):
|
||||||
|
```
|
||||||
|
sandwiches_with_costs = [["blt", 5], ["grilled cheese", 7], ["turkey_club_with_pesto", 9], ["ramenburger", 6], ["portobello and garlic aioli", 10]]
|
||||||
|
```
|
||||||
|
Create an empty hash (call it whatever you want) and then iterate over sandwiches_with_costs and add sandwich names as keys and cost amounts as values to the hash.
|
||||||
|
|
||||||
|
|
||||||
|
## Hashes
|
||||||
|
|
||||||
|
Perform the following tasks using hash methods (note: you might also need to use some string and array methods).
|
||||||
|
|
||||||
|
Given the hash:
|
||||||
|
|
||||||
|
```
|
||||||
|
breakfast_prefs = {
|
||||||
|
juice: "orange",
|
||||||
|
syrup: "maple",
|
||||||
|
potatoes: "mashed with molasses",
|
||||||
|
lettuce: "iceberg",
|
||||||
|
protein: "GNC Pro Performance AMP Amplified Wheybolic Extreme 60™ Original",
|
||||||
|
cups_of_coffee: 3,
|
||||||
|
pink_slime: false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Return an array containing only the keys of `breakfast_prefs`.
|
||||||
|
2. Return an array containing only the values of `breakfast_prefs`.
|
||||||
|
3. Change the value of `:syrup` to `"boysenberry"`.
|
||||||
|
4. Return a hash with the key-value pairs whose value is of type string.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
## USING RUBY METHODS
|
||||||
|
|
||||||
|
|
||||||
|
## PART ONE
|
||||||
|
|
||||||
|
arr = [["Live", "Laugh", "Love"], {hello: 'hi back'}, false, 333.333, nil, nil, ["Joy", "Joke", "Jerk"]]
|
||||||
|
|
||||||
|
arr.each do |item|
|
||||||
|
puts item.class
|
||||||
|
end
|
||||||
|
|
||||||
|
# select and class
|
||||||
|
new_array = arr.select do |item|
|
||||||
|
item.class == Array
|
||||||
|
end
|
||||||
|
|
||||||
|
new_arr.flatten.permutation.to_a
|
||||||
|
|
||||||
|
new_array2 = arr.reject do |item|
|
||||||
|
item.class == Hash
|
||||||
|
end
|
||||||
|
|
||||||
|
## PART TWO
|
||||||
|
|
||||||
|
numbers = [4, 7, 8, 7, 9, 0, 4]
|
||||||
|
|
||||||
|
#permuation.to_a
|
||||||
|
permutations = numbers.permutation.to_a
|
||||||
|
|
||||||
|
# select, first, and last
|
||||||
|
perms = permutations.select do |item|
|
||||||
|
item.first == 7 && item.last == 7
|
||||||
|
end
|
||||||
|
|
||||||
|
result1 = numbers.reduce(:+)
|
||||||
|
|
||||||
|
result2 = numbers.reduce(:*)
|
||||||
|
|
||||||
|
|
||||||
|
## PART THREE
|
||||||
|
|
||||||
|
strings = ["Paloma", "Grits", "Ziti", "Carbohydrates", "Grits", "Corn", "Wizard_robe", "Ziti", "Corn", "Corn", "Maize"]
|
||||||
|
|
||||||
|
hash = {}
|
||||||
|
|
||||||
|
strings.uniq.each do |hashkey|
|
||||||
|
if hashkey == "Maize" then hash[hashkey] = "Not Fun"
|
||||||
|
else hash[hashkey] = "Fun" end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
## PART FOUR
|
||||||
|
|
||||||
|
students = [
|
||||||
|
"Amber",
|
||||||
|
"Nicole",
|
||||||
|
"Christine",
|
||||||
|
"Dan",
|
||||||
|
"Ashleigh",
|
||||||
|
"Jordan",
|
||||||
|
"Alex",
|
||||||
|
"Emily",
|
||||||
|
"John",
|
||||||
|
"Sharon",
|
||||||
|
"Levi",
|
||||||
|
"Pauline",
|
||||||
|
"Masha",
|
||||||
|
"Matt",
|
||||||
|
"Andy",
|
||||||
|
"Sammy",
|
||||||
|
"Dominic",
|
||||||
|
"Vincent",
|
||||||
|
"Jesse",
|
||||||
|
"Juan",
|
||||||
|
"Josh",
|
||||||
|
"Derek"
|
||||||
|
];
|
||||||
|
|
||||||
|
shuffled_students = students.shuffle
|
||||||
|
|
||||||
|
p shuffled_students.each_slice(3) { |stuff| p stuff };
|
||||||
|
|
||||||
|
# Go to jail
|
||||||
|
p students.sample
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
## SELECTED RUBY METHODS
|
||||||
|
|
||||||
|
Here are some exercises to become more acquainted with the following Ruby methods:
|
||||||
|
|
||||||
|
1. `.each`
|
||||||
|
2. `.class`
|
||||||
|
3. `.select`
|
||||||
|
4. `.reject`
|
||||||
|
5. `.flatten`
|
||||||
|
6. `.permutation.to_a`
|
||||||
|
7. `.first`
|
||||||
|
8. `.last`
|
||||||
|
9. `.count`
|
||||||
|
10. `.reduce`
|
||||||
|
11. `.uniq`
|
||||||
|
12. `.shuffle`
|
||||||
|
13. `.each_slice`
|
||||||
|
14. `.sample`
|
||||||
|
15. `.each_cons`
|
||||||
|
|
||||||
|
|
||||||
|
### 1
|
||||||
|
Given the following array
|
||||||
|
|
||||||
|
```
|
||||||
|
arr = [["Live", "Laugh", "Love"], {hello: 'hi back'}, false, 333.333, nil, nil, ["Joy", "Joke", "Jerk"]]
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Use `.each` and `.class` to print the class of each array element to the console
|
||||||
|
|
||||||
|
2. Use `.select` and `.class` to return an array of only those elements whose class is Array. http://ruby-doc.org/core-2.3.0/Enumerable.html#method-i-select
|
||||||
|
|
||||||
|
3. Use `.reject` and `.class` to return an array of only those elements whose class is not Hash. http://ruby-doc.org/core-2.3.0/Enumerable.html#method-i-reject
|
||||||
|
|
||||||
|
4. Use `.flatten` on the result of your previous `.select` operation to flatten out the array
|
||||||
|
|
||||||
|
5. Use `.permutation.to_a` on the flattened result to return all possible permutations of all the items within the inner arrays.
|
||||||
|
|
||||||
|
6. Use `.count` to get the number of those permutations.
|
||||||
|
|
||||||
|
### 2
|
||||||
|
|
||||||
|
Given the following array
|
||||||
|
|
||||||
|
```
|
||||||
|
numbers = [4, 7, 8, 7, 9, 0, 4]
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Use `.permutation.to_a` and `.count` to return a count of all permutations
|
||||||
|
|
||||||
|
2. `.select` only those permutations where the `.first` number is 7 and the `.last` number is also 7, and return a `.count` of those permutations.
|
||||||
|
|
||||||
|
3. Use `.reduce` to get the sum of the array.
|
||||||
|
|
||||||
|
4. Use `.reduce` to get the product of the array.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 3
|
||||||
|
|
||||||
|
Given the following array
|
||||||
|
|
||||||
|
```
|
||||||
|
strings = ["Paloma", "Grits", "Ziti", "Carbohydrates", "Grits", "Corn", "Wizard_robe", "Ziti", "Corn", "Corn", "Maize"]
|
||||||
|
```
|
||||||
|
|
||||||
|
and the empty hash
|
||||||
|
|
||||||
|
```
|
||||||
|
hash = {}
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Using `.each` and `.uniq`, populate the hash using the elements in the array as keys. Remember that keys must be unique, so don't include any double-ups. Set the values of those keys to "Fun" except for Maize, which is "Not Fun".
|
||||||
|
|
||||||
|
|
||||||
|
### 4
|
||||||
|
|
||||||
|
```
|
||||||
|
students = [
|
||||||
|
"Amber",
|
||||||
|
"Nicole",
|
||||||
|
"Christine",
|
||||||
|
"Dan",
|
||||||
|
"Ashleigh",
|
||||||
|
"Jordan",
|
||||||
|
"Alex",
|
||||||
|
"Emily",
|
||||||
|
"John",
|
||||||
|
"Sharon",
|
||||||
|
"Levi",
|
||||||
|
"Pauline",
|
||||||
|
"Masha",
|
||||||
|
"Matt",
|
||||||
|
"Andy",
|
||||||
|
"Sammy",
|
||||||
|
"Dominic",
|
||||||
|
"Vincent",
|
||||||
|
"Jesse",
|
||||||
|
"Juan",
|
||||||
|
"Josh",
|
||||||
|
"Derek"
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Pretend that group projects are coming up again, and you have to split the class up into random groups of three. Use `.shuffle` and `.each_slice` to generate groups of three (there will be one remainder). http://ruby-doc.org/core-2.3.0/Enumerable.html#method-i-each_slice.
|
||||||
|
|
||||||
|
2. Use `.sample` to return a single random student to be taken to jail. http://ruby-doc.org/core-2.1.4/Array.html#method-i-sample
|
||||||
|
|
||||||
|
|
||||||
|
### 5. Make your own problem
|
||||||
|
|
||||||
|
Look into the Ruby method `.each_cons`, http://ruby-doc.org/core-2.3.0/Enumerable.html#method-i-each_cons
|
||||||
|
|
||||||
|
Make your own problem where the answer should use `.each_cons`.
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,448 @@
|
|||||||
|
# Rails - PERSONAL SHOPPER
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### Rails many-to-many and (bonus) one-to-many practise
|
||||||
|
|
||||||
|
## APP
|
||||||
|
|
||||||
|
You are a personal shopper for a variety of clients. These people are incapable of shopping for whatever reason--perhaps they have `bone-itis`. Shopping carts and products have a **many-to-many** relationship. They are interrelated in the app by adding each to each. For example: On a shopping cart page, you can add many products to a shopping cart. On a product page, you can add many shopping carts to the product. They are mirror images of each other.
|
||||||
|
|
||||||
|
##### app pages
|
||||||
|
- an index of shopping carts (one for each client)
|
||||||
|
- an index of products
|
||||||
|
- a show page for each shopping cart, on which you can add products to the cart
|
||||||
|
- a show page for each product, on which you can add the product to some carts
|
||||||
|
|
||||||
|
##### bonus
|
||||||
|
- product reviews on the product's show page (one-to-many)
|
||||||
|
|
||||||
|
The purpose of tonight's homework is not to make a full CRUD app, but to display and test relations between tables, especially the two-way nature of a `many-to-many` relationship. Some of this will be tutorial-style, the rest left for you to figure out.
|
||||||
|
</br>
|
||||||
|
</br>
|
||||||
|
|
||||||
|
**Example shopping carts index** (no styling yet)
|
||||||
|
|
||||||
|

|
||||||
|
</br></br>
|
||||||
|
|
||||||
|
**Example products index** (no styling yet)
|
||||||
|
|
||||||
|

|
||||||
|
</br></br>
|
||||||
|
|
||||||
|
|
||||||
|
**Example shopping cart show** (no styling yet)
|
||||||
|
There is a dropdown menu to add products to this cart.
|
||||||
|
|
||||||
|

|
||||||
|
</br></br>
|
||||||
|
|
||||||
|
|
||||||
|
**Example product show** (no styling yet)
|
||||||
|
There is a dropwdown menu to add carts to this product.
|
||||||
|
|
||||||
|

|
||||||
|
</br></br>
|
||||||
|
|
||||||
|
|
||||||
|
## START
|
||||||
|
|
||||||
|
`rails new shopping_carts_app --database=postgresql`
|
||||||
|
|
||||||
|
**Go into your new rails app directory**
|
||||||
|
|
||||||
|
`rake db:create`
|
||||||
|
|
||||||
|
Test that you have made a postgresql database (not sqlite) by typing `rails dbconsole` then quitting.
|
||||||
|
|
||||||
|
## GENERATORS
|
||||||
|
|
||||||
|
This time we will use generators for our models and controllers. We have two models and controllers: **shopping carts** and **products**. Go ahead and generate all of the following:
|
||||||
|
|
||||||
|
####Shopping carts
|
||||||
|
|
||||||
|
```rails g model ShoppingCart```
|
||||||
|
|
||||||
|
This will give you a **migration file**, and a model file **shopping_cart.rb**
|
||||||
|
|
||||||
|
|
||||||
|
```rails g controller shopping_carts```
|
||||||
|
|
||||||
|
This will give you a controller file **shopping_carts_controller.rb** and a folder for your shopping_carts views.
|
||||||
|
|
||||||
|
|
||||||
|
Notice that our model is uppercase-camelcase `ShoppingCart` singular-- the associated controller command will therefore need to be lowercase-snakecase plural `shopping_carts`.
|
||||||
|
|
||||||
|
Remember, the model generator adds a migration file so you **don't need to generate a migration.**
|
||||||
|
|
||||||
|
Do the same for Products and Reviews.
|
||||||
|
|
||||||
|
####Products
|
||||||
|
|
||||||
|
```rails g model Product```
|
||||||
|
|
||||||
|
```rails g controller products```
|
||||||
|
|
||||||
|
|
||||||
|
#### Tables
|
||||||
|
We will have THREE tables that we will make soon:
|
||||||
|
1. shopping_carts
|
||||||
|
2. products
|
||||||
|
3. products_shopping_carts (a join table)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## MODELS
|
||||||
|
|
||||||
|
#### 1. SHOPPING CARTS
|
||||||
|
Shopping carts have a **many-to-many** relationship with products. A shopping cart can have many products, and a product can belong to many shopping carts. Later we will build a join table for shopping carts and products. In your ShoppingCart model file, the relationship is specified like this: `has_and_belongs_to_many :products`
|
||||||
|
|
||||||
|
#### 2. PRODUCTS
|
||||||
|
Products have a **many-to-many** relationship with shopping carts. A product can have many shopping carts, and a shopping cart can belong to many products. Later we will build a join table for products and shopping carts. In your Product model file the relationship is specified like this: `has_and_belongs_to_many :shopping_carts`.
|
||||||
|
|
||||||
|
|
||||||
|
## MIGRATION FILES
|
||||||
|
|
||||||
|
```
|
||||||
|
Since shopping_carts and products have a *many-to-many** relationship, neither of them needs a foreign key to reference the other.
|
||||||
|
```
|
||||||
|
|
||||||
|
shopping_carts
|
||||||
|
1. client_name - string
|
||||||
|
|
||||||
|
products
|
||||||
|
1. name - string
|
||||||
|
2. price - decimal
|
||||||
|
3. manufacturer - string
|
||||||
|
4. img_url - text
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### JOIN TABLE
|
||||||
|
While our model generators have conveniently created our migration files, now we must generate our own migration file for the join table.
|
||||||
|
|
||||||
|
`rails g migration CreateJoinTable shopping_carts products`
|
||||||
|
|
||||||
|
In the migration file, delete the t.index entries within createTable and replace them with
|
||||||
|
|
||||||
|
```
|
||||||
|
t.integer :shopping_cart_id
|
||||||
|
t.integer :product_id
|
||||||
|
```
|
||||||
|
|
||||||
|
Double check all your migration files and run your migrations. `rake db:migrate`
|
||||||
|
|
||||||
|
|
||||||
|
## SEEDING
|
||||||
|
|
||||||
|
In your `seeds.rb`, create a bunch of shopping carts and products. Distribute the products between shopping carts of your choosing, but make sure there are carts that do not have all the products. (See below). Also, feel free to use the seed below.
|
||||||
|
|
||||||
|
For convenience, you can create **multiple entries** for a single model ---
|
||||||
|
|
||||||
|
This makes an array called `items` that will contain multiple Products to seed. Each product will be conveniently seeded from that array when you run rake db:seed.
|
||||||
|
|
||||||
|
```
|
||||||
|
items = Product.create([
|
||||||
|
{
|
||||||
|
name: 'Cloud',
|
||||||
|
price: 20.45,
|
||||||
|
manufacturer: 'Pufft Corp',
|
||||||
|
img_url: 'image here'
|
||||||
|
},{
|
||||||
|
name: 'Moss',
|
||||||
|
price: 2.90,
|
||||||
|
manufacturer: 'Gardeny Glades',
|
||||||
|
img_url: 'image here'
|
||||||
|
},{
|
||||||
|
name: 'Health Insurance',
|
||||||
|
price: 9999999999,
|
||||||
|
manufacturer: 'Kill U Corp',
|
||||||
|
img_url: 'image here'
|
||||||
|
},{
|
||||||
|
name: 'Regret',
|
||||||
|
price: 0,
|
||||||
|
manufacturer: 'Yourself',
|
||||||
|
img_url: 'image here'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
`For now, items[0] has the name 'Cloud'. Remember for later.`
|
||||||
|
|
||||||
|
This creates an array called carts, and each cart will be conveniently seeded from this array when you run rake db:seed.
|
||||||
|
|
||||||
|
```
|
||||||
|
carts = ShoppingCart.create([
|
||||||
|
{ client_name: 'Pepe' },
|
||||||
|
{ client_name: 'Penelope' },
|
||||||
|
{ client_name: 'Bob' },
|
||||||
|
{ client_name: 'Doot'},
|
||||||
|
{ client_name: 'Schnipper'}
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
`For now, carts[1] has the username 'Penelope'. Remember for later.`
|
||||||
|
|
||||||
|
Finally, to seed items in a **many-to-many** relationship, you can push items into the array associated through the join table. This push goes after the products array and items array have been established. Pushing into a many-to-many array with seed arrays:
|
||||||
|
|
||||||
|
```
|
||||||
|
carts[0].products.push(items[0], items[1])
|
||||||
|
carts[1].products.push(items[1])
|
||||||
|
```
|
||||||
|
|
||||||
|
#### side-note
|
||||||
|
If you create your seeds independently without using arrays, assuming you used cart, item1, item2 as variable names for those seeds ---
|
||||||
|
|
||||||
|
Pushing into a many-to-many array would work like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
cart.products.push(item1, item2)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### rake db:seed
|
||||||
|
Seed your database: `rake db:seed`
|
||||||
|
|
||||||
|
If you **really mess up**, you can `rake db:reset`, and this will empty your database and re-run the seed.
|
||||||
|
|
||||||
|
Check the database has been seeded properly in `rails dbconsole`:
|
||||||
|
|
||||||
|
`SELECT * FROM shopping_carts;`
|
||||||
|
`SELECT * FROM products;`
|
||||||
|
`SELECT * FROM products_shopping_carts;`
|
||||||
|
</br>
|
||||||
|
</br>
|
||||||
|
</br>
|
||||||
|
|
||||||
|
# STAGE ONE
|
||||||
|
#### ROUTES
|
||||||
|
|
||||||
|
- For now, add resources for `shopping carts` and `products`
|
||||||
|
- Set your `root to: 'shopping_carts#index'`
|
||||||
|
|
||||||
|
|
||||||
|
#### CONTROLLERS
|
||||||
|
|
||||||
|
- **Shopping carts**
|
||||||
|
- We will need an `index` and `show`.
|
||||||
|
|
||||||
|
- **Products**
|
||||||
|
- We will need an `index` and a `show`.
|
||||||
|
|
||||||
|
#### VIEWS
|
||||||
|
|
||||||
|
#####SHOPPING CARTS
|
||||||
|
|
||||||
|
We will want an **index page** to see all our shopping carts. Provide a link to the products index page.
|
||||||
|
|
||||||
|
This shopping carts **index page** will have a list of carts with the client_names, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
Pepe's shopping cart
|
||||||
|
Penelope's shopping cart
|
||||||
|
```
|
||||||
|
|
||||||
|
Each will be a link to the show page of that client's particular cart.
|
||||||
|
|
||||||
|
The **show page** of each cart will list all the products it contains.
|
||||||
|
Hint: `<% @cart.products.each do |item| %>`
|
||||||
|
|
||||||
|
Each product name will be a link to that particular product's own show page.
|
||||||
|
|
||||||
|
Note: remember to give the user the ability to navigate back to the shopping cart index page from each cart's show page.
|
||||||
|
|
||||||
|
|
||||||
|
#####PRODUCTS
|
||||||
|
|
||||||
|
We will want an **index page** so that we can browse the products. Each product will link to its own **show page**.
|
||||||
|
|
||||||
|
Also, on the products **index page**, provide a link to the shopping cart index page.
|
||||||
|
|
||||||
|
On the product's **show page** add all the product details. List all the clients who have that product in a cart with a link to the client's shopping cart.
|
||||||
|
|
||||||
|
</br>
|
||||||
|
|
||||||
|
# STAGE 2 - ADD SHOPPING CART TO PRODUCT
|
||||||
|
From a product's **show** page, we want to be able to conveniently put that product in one of our client's shopping carts.
|
||||||
|
|
||||||
|
#####PRODUCTS
|
||||||
|
|
||||||
|
On the products **show page**, give the user the ability to add that product to one of the client's carts using a dropdown menu to select which cart.
|
||||||
|
|
||||||
|
The process is as follows:
|
||||||
|
|
||||||
|
Make a **custom action** in your products controller. This action will push an incoming cart into the array of carts associated with the chosen product. Don't copy and paste:
|
||||||
|
|
||||||
|
```
|
||||||
|
def add_cart
|
||||||
|
product = Product.find(params[:id])
|
||||||
|
cart = ShoppingCart.find(params[:cart_id])
|
||||||
|
product.shopping_carts << cart
|
||||||
|
redirect_to product_path(product)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
**Before** you add this to your products controller, look at each line and write down what you expect each line will do.
|
||||||
|
|
||||||
|
Now we have a custom action, but Rails doesn't know how to route to it. To do this, in `config/routes.rb` we can add a new member to our product's routes:
|
||||||
|
|
||||||
|
```
|
||||||
|
resources :products do
|
||||||
|
member do
|
||||||
|
put 'add_cart'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
So, instead of just resources :products, we have a new member and we have specified that it is a PUT route. Type `rake routes` to see that your routes now contain a path to your new method.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Back to your **show page** for your product, you will want a form that will allow you to choose a cart to place the item into. You will need to give all of the carts to the show page: in the products `show` action: `@carts = ShoppingCart.all`
|
||||||
|
|
||||||
|
|
||||||
|
We will do this without a form helper for now. Do not copy and paste:
|
||||||
|
|
||||||
|
```
|
||||||
|
<form action="/products/<%= @product.id %>/add_cart" method="post">
|
||||||
|
<input type="hidden" name="_method" value="put">
|
||||||
|
<select name="cart_id">
|
||||||
|
<% @carts.each do |cart| %>
|
||||||
|
<% unless @product.shopping_carts.include?(cart) %>
|
||||||
|
<option value="<%= cart.id %>"><%= cart.client_name %></option>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</select><br><br>
|
||||||
|
<input type="submit" value="Add to Cart">
|
||||||
|
</form>
|
||||||
|
```
|
||||||
|
|
||||||
|
Go over each line and write down what you expect it does. When you have coded it into your view,
|
||||||
|
run the server and go to the page, and Inspect Element. This is what your form looks like in HTML.
|
||||||
|
|
||||||
|
Your form will not work yet. There is one more piece. Because we built a form without form helpers, Rails might not like our authenticity tokens. To bypass the authenticity tokens, put
|
||||||
|
|
||||||
|
``` skip_before_action :verify_authenticity_token ```
|
||||||
|
|
||||||
|
before your actions in the products controller.
|
||||||
|
|
||||||
|
|
||||||
|
# STAGE 3 - ADD PRODUCT TO SHOPPING CART
|
||||||
|
|
||||||
|
From a cart's **show** page, we want to be able to conveniently add a product to that cart.
|
||||||
|
|
||||||
|
This will be a mirror image of stage 2. Same thing, different direction.
|
||||||
|
|
||||||
|
#####SHOPPING CARTS
|
||||||
|
|
||||||
|
On the shopping carts **show page**, give the user the ability to add a product to the cart using a dropdown menu to select which product.
|
||||||
|
|
||||||
|
The process is as follows:
|
||||||
|
|
||||||
|
Make a **custom action** in your shopping carts controller. This action will push an incoming product into the array of products associated with the current cart. Don't copy and paste:
|
||||||
|
|
||||||
|
```
|
||||||
|
def add_product
|
||||||
|
cart = ShoppingCart.find(params[:id])
|
||||||
|
product = Product.find(params[:product_id])
|
||||||
|
cart.products << product
|
||||||
|
redirect_to shopping_cart_path(cart)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
**Before** you add this to your shopping carts controller, look at each line and write down what you expect each line will do.
|
||||||
|
|
||||||
|
Now we have a custom action, but Rails doesn't know how to route to it. To do this, in `config/routes.rb` we can add a new member to our shopping cart's routes:
|
||||||
|
|
||||||
|
```
|
||||||
|
resources :shopping_carts do
|
||||||
|
member do
|
||||||
|
put 'add_product'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
So, instead of just resources :shopping_carts, we have a new member and we have specified that it is a PUT route. Type `rake routes` to see that your routes now contain a path to your new method.
|
||||||
|
|
||||||
|
|
||||||
|
Back to your **show page** for your cart, you will want a form that will allow you to choose a product to place into the cart. You will need to give all of the products to the show page: in the shopping carts `show` action: `@products = Product.all`
|
||||||
|
|
||||||
|
|
||||||
|
We will do this without a form helper for now. Do not copy and paste:
|
||||||
|
|
||||||
|
```
|
||||||
|
<form action="/shopping_carts/<%= @cart.id %>/add_product" method="post">
|
||||||
|
<input type="hidden" name="_method" value="put">
|
||||||
|
<select name="product_id">
|
||||||
|
<% @products.each do |product| %>
|
||||||
|
<% unless @cart.products.include?(product) %>
|
||||||
|
<option value="<%= product.id %>"><%= product.name %></option>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</select><br><br>
|
||||||
|
<input type="submit" value="Add to Cart">
|
||||||
|
</form>
|
||||||
|
```
|
||||||
|
|
||||||
|
Go over each line and write down what you expect it does. When you have coded it into your view,
|
||||||
|
run the server and go to the page, and Inspect Element. This is what your form looks like in HTML.
|
||||||
|
|
||||||
|
Your form will not work yet. There is one more piece. Because we built a form without form helpers, Rails might not like our authenticity tokens. To bypass the authenticity tokens, put
|
||||||
|
|
||||||
|
``` skip_before_action :verify_authenticity_token ```
|
||||||
|
|
||||||
|
before your actions in the shopping carts controller.
|
||||||
|
|
||||||
|
|
||||||
|
#### CONGRATULATIONS! You just added two-way functionality for a many-to-many relationship
|
||||||
|
|
||||||
|
</br>
|
||||||
|
|
||||||
|
## BONUS ONE - REVIEWS
|
||||||
|
On the **show page** of a product, display all the reviews for that product.
|
||||||
|
|
||||||
|
```rails g model Review```
|
||||||
|
|
||||||
|
```rails g controller reviews```
|
||||||
|
|
||||||
|
Reviews belong_to a product. `belongs_to :products`.
|
||||||
|
|
||||||
|
reviews migration file - **remember to add the foreign key**
|
||||||
|
|
||||||
|
1. author - string
|
||||||
|
2. content - text
|
||||||
|
3. `t.belongs_to :product` <-- foreign key
|
||||||
|
|
||||||
|
Seed:
|
||||||
|
|
||||||
|
```
|
||||||
|
Review.create({
|
||||||
|
author: 'Dale',
|
||||||
|
content: 'I think it is ok',
|
||||||
|
product_id: 1
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## BONUS TWO, CRUD STUFF
|
||||||
|
|
||||||
|
--
|
||||||
|
*If you have gotten this far, it's time to Work It On Out* : Include a form for submitting a new review on the product **show page**. You should be able to successfully add reviews to products.
|
||||||
|
|
||||||
|
##### SHOPPING CARTS
|
||||||
|
Allow the user to `create` a new (empty) shopping cart.
|
||||||
|
Allow the user to `delete` a shopping cart with a delete link next to the cart's name. Remember to redirect.
|
||||||
|
|
||||||
|
On the shopping cart **show page** allow the user to `remove` a product from the cart.
|
||||||
|
|
||||||
|
## BONUS THREE
|
||||||
|
|
||||||
|
2. Add more products, carts, and reviews using either the rails console, or the dbconsole.
|
||||||
|
3. Show the number of products in a cart on the shopping cart index page.
|
||||||
|
4. Generate and run a new migration that adds a column to your products table (the column could be called `weight` and accepts an integer, for example).
|
||||||
|
5. Give the option to edit and delete a review, and have it work.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 37 KiB |
@ -0,0 +1,52 @@
|
|||||||
|
## RUBY CLASSES
|
||||||
|
|
||||||
|
#1. Classes
|
||||||
|
Watch the short video [here](https://www.youtube.com/watch?v=r6wVziWXYWI). 6 mins 23 seconds.
|
||||||
|
|
||||||
|
|
||||||
|
##Exercises:
|
||||||
|
1. Create a Dog class that takes in a name and puts `"Meet #{name}, your new dog!"` on `initialize`.
|
||||||
|
- Assign the dog a random fur color on initialize
|
||||||
|
2. Create a Bird class that takes in an adjective and a name and puts `"#{name} is a(n) #{adjective} bird!"` on `initialize`.
|
||||||
|
- Assign the bird a species at random on initialize
|
||||||
|
|
||||||
|
#2. Instance Methods
|
||||||
|
Watch the short video here [here](https://www.youtube.com/watch?v=c2a2bZf3LH4). 8 mins 22 seconds.
|
||||||
|
|
||||||
|
|
||||||
|
##Exercises:
|
||||||
|
1. Add instance methods to your dog
|
||||||
|
- Add a `bark` instance method to your dog that puts `"#{name} is barking!"`
|
||||||
|
- Add a `growl` instance mthods that puts "Grrrrrrr..."
|
||||||
|
3. Add instance methods to your bird
|
||||||
|
- Add a `hungry` method that puts `"#{name} wants a cracker!"`
|
||||||
|
- Add a `fly` methods that puts `"Flap! #{name} is taking flight!"`
|
||||||
|
4. Make your bird's ajective and name accessible
|
||||||
|
|
||||||
|
#3. Class Methods and 'Self'
|
||||||
|
Watch the short video [here](https://www.youtube.com/watch?v=0r93ZhzpeqI). 8 mins 28 seconds.
|
||||||
|
|
||||||
|
##Exercises:
|
||||||
|
1. Experiment with `self`
|
||||||
|
- Add a class method `self.what_is_self` to your Bird class and have it put `self`.
|
||||||
|
- Add an instance method `what_is_self` to your Bird class and have it put `self`.
|
||||||
|
- Try calling both of these methods in Pry and see what they return.
|
||||||
|
2. Add a class method to make puppies!
|
||||||
|
- add an instance variable of quality to your dog (here we will put a characteristic like 'playful', 'brave', 'loyal')
|
||||||
|
- add a class method of `make_puppy` to your dog class that takes in two dogs and returns a new dog.
|
||||||
|
- the new dog should have fur color of the first dog and the quality of the second dog.
|
||||||
|
- make puppies!
|
||||||
|
|
||||||
|
#4. Inheritance
|
||||||
|
Watch the short video [here](https://www.youtube.com/watch?v=BJWcH8Pnafw). 6 mins 56 seconds.
|
||||||
|
|
||||||
|
|
||||||
|
##Exercises:
|
||||||
|
1. Create a class called `Dessert` that has instance variables of `@name` and `@sugar_content`
|
||||||
|
2. Give it an instance method of `eat` that puts `"Yum! This #{name} is sooooo delicious!"`
|
||||||
|
3. Make two new classes called `Pie` and `DeepFriedDessert` that inherit from `Dessert`
|
||||||
|
4. Give the `DeepFriedDessert` its own `eat` method that instead puts `"Yum! This #{name} is sooo...ack! ugh! *heart-attack*"`
|
||||||
|
5. Make a new class `IceCream` that inherits from `Dessert` use `super` to get the instance variables of `@name` and `@sugar-content`. Also give `IceCream` its own unique instance variable of `@toppings`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
# SQL Practise
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Learning Objectives
|
||||||
|
1. Practice creating a database from the command line
|
||||||
|
2. Practice creating an SQL schema
|
||||||
|
3. Practise seeding an SQL database
|
||||||
|
4. Practice querying a database using SQL
|
||||||
|
|
||||||
|
|
||||||
|
#1. CREATION
|
||||||
|
- Open up the psql server by typing `psql` in terminal
|
||||||
|
- Make a database called 'realty' with `CREATE DATABASE realty;`
|
||||||
|
- You can check if this has worked by typing `\l`, and you will get a list of your databases
|
||||||
|
- Exit the psql server with `\q`
|
||||||
|
|
||||||
|
|
||||||
|
#2. SCHEMA
|
||||||
|
|
||||||
|
In your homework folder, touch an SQL file called `schema.sql`. Create a schema based off the following ERD.
|
||||||
|
|
||||||
|
Note: VARCHAR is a text type that is character-limited, typically up to 255.
|
||||||
|
(See below for create table SQL syntax).
|
||||||
|
|
||||||
|
|
||||||
|
- apartments should have:
|
||||||
|
- id - serial primary key
|
||||||
|
- tenant - varchar
|
||||||
|
|
||||||
|
- offices should have:
|
||||||
|
- id - serial primary key
|
||||||
|
- sq_ft - integer
|
||||||
|
- cubicles - integer
|
||||||
|
- bathrooms - integer
|
||||||
|
- company - varchar
|
||||||
|
|
||||||
|
- storefronts should have:
|
||||||
|
- kitchen - boolean
|
||||||
|
- sq_ft - integer
|
||||||
|
- outdoor_seating - boolean
|
||||||
|
|
||||||
|
|
||||||
|
Your create table syntax will look something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
CREATE TABLE apartments (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
tenant VARCHAR(255)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Etc. You can create multiple tables in the same .sql file.
|
||||||
|
|
||||||
|
From the command line load the schema `schema.sql` into the database:
|
||||||
|
- Go into the directory where `schema.sql` is located.
|
||||||
|
- In terminal, NOT in the the psql server, type `psql -d realty < schema.sql`
|
||||||
|
This tells the database (-d) called realty to 'eat' the contents of schema.sql.
|
||||||
|
|
||||||
|
You can check if this has worked by going into your psql server and connecting
|
||||||
|
to the realty database with `\c realty`. The `\c` command is used to connect to any database you have stored in psql.
|
||||||
|
|
||||||
|
Now type `\dt` and you should see a list of the tables you have created.
|
||||||
|
|
||||||
|
To see a list of your columns in a table, for example the apartment table, type `SELECT * FROM apartments`
|
||||||
|
|
||||||
|
Quit psql again with `\q`
|
||||||
|
|
||||||
|
|
||||||
|
#3. SEED
|
||||||
|
|
||||||
|
- Create a new file called `seed.sql`, and in this file you should
|
||||||
|
- **Practise writing the proper INSERT commands that will add new entries into your apartment, office and storefront tables.** You should create at least 3 entries for each table. Vary the attributes of each entry so no two are alike.
|
||||||
|
|
||||||
|
</br>
|
||||||
|
- From the command line, load this seed file into your database. In the directory where your seed file is located, type the same command as before but substitute the
|
||||||
|
schema.sql for seed.sql: `psql -d realty < seed.sql`. You should see a list of INSERTs.
|
||||||
|
|
||||||
|
|
||||||
|
#4. CRUD
|
||||||
|
|
||||||
|
Perform these operations from the `psql` command line
|
||||||
|
|
||||||
|
- Practice editing tables
|
||||||
|
- Change the tenant of an apartment
|
||||||
|
- Change the number of bathrooms in an office
|
||||||
|
- Practice deleting entries
|
||||||
|
- delete the storefront with the lowest square footage
|
||||||
|
- delete the office with the most cubicles
|
||||||
|
- Practise more inserts
|
||||||
|
- add a storefront that has outdoor seating
|
||||||
|
- add an office with ten bathrooms
|
||||||
|
|
||||||
|
|
||||||
|
#5. QUERIES
|
||||||
|
Create a new markdown file `realty.md` and write the SQL commands you would use to retrieve the following information from your database. Test each command in PSQL to make sure it is correct:
|
||||||
|
|
||||||
|
- The average square footage of all offices
|
||||||
|
- The total number of apartments
|
||||||
|
- The apartments where there is no tenant
|
||||||
|
- The names of all of the companies
|
||||||
|
- The number of cubicles and bathrooms in the 3rd office
|
||||||
|
- The storefronts that have kitchens
|
||||||
|
- The storefront with the highest square footage and outdoor seating
|
||||||
|
- The office with the lowest number of cubicles
|
||||||
|
- The office with the most cubicles and bathrooms combined
|
||||||
|
|
||||||
|
W3 schools has good guides for sql commands along the left sidebar: http://www.w3schools.com/sql/default.asp
|
||||||
|
|
||||||
@ -0,0 +1,140 @@
|
|||||||
|
# SQL Practise II
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```
|
||||||
|
- one-to-many relationship between two models
|
||||||
|
- using foreign keys
|
||||||
|
- table joins: joining tables at foreign keys
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##Objectives
|
||||||
|
- Practice setting up a one-to-many relationship using foreign keys
|
||||||
|
- Practise returning tables joined by foreign key
|
||||||
|
|
||||||
|
|
||||||
|
##Schema - one-to-many
|
||||||
|
|
||||||
|
We are going to relate two models: `users` and `regions`, for a potential meetup app
|
||||||
|
|
||||||
|
- Create a database, call it `meetup_app`
|
||||||
|
- Create a `users` table. Make it either in a `schema.sql` file or straight into the psql command line. Each `user` should have:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
- region_id
|
||||||
|
|
||||||
|
In the future, we would want our users to be able to subscribe to a regional group so they can see all the other users in their area. In this case, we want each user only to be associated with one region at a time. This is a **one-to-many** relationship, where:
|
||||||
|
|
||||||
|
```
|
||||||
|
*many* users belong to *one* region.
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
*one* region has *many* users.
|
||||||
|
```
|
||||||
|
|
||||||
|
</br>
|
||||||
|
NOTE: There are a few basic data relationships used extensively in Rails applications, such as **one-to-many** and also **many-to-many**.
|
||||||
|
|
||||||
|
Here is a good overview of SQL relationships including joins:
|
||||||
|
http://code.tutsplus.com/articles/sql-for-beginners-part-3-database-relationships--net-8561
|
||||||
|
|
||||||
|
In a **one-to-many** relationship, the foreign key lives in the **many**. In this case, `users` is the **many**, because **many** users belong to **one** `region`.
|
||||||
|
|
||||||
|
You might notice that the `users` schema has a `region_id`. This is the foreign key. It will be a number: the id of the region to which the user belongs.
|
||||||
|
|
||||||
|
</br>
|
||||||
|
|
||||||
|
```
|
||||||
|
CONCEPTUAL QUESTION:
|
||||||
|
|
||||||
|
Why is it that the foreign key lives in the many? Would it make sense to put the foreign key in the one?
|
||||||
|
```
|
||||||
|
|
||||||
|
- Create a `regions` table. Each region should have
|
||||||
|
- A unique ID
|
||||||
|
- A name
|
||||||
|
- A radius in miles
|
||||||
|
|
||||||
|
```
|
||||||
|
CONCEPTUAL QUESTION:
|
||||||
|
|
||||||
|
**NOTE:** the `regions` table has nothing to associate any users with it. Why do we not need anything here to relate or 'store' users?
|
||||||
|
```
|
||||||
|
|
||||||
|
If you put your schemas into a `schema.sql` file, run it with `psql -d meetup_app < schema.sql`.
|
||||||
|
|
||||||
|
|
||||||
|
## Seed
|
||||||
|
|
||||||
|
- In a regionseed.sql file, write the INSERTS for three different `regions`. Alternatively, write the INSERTS straight into the psql command line. If you made a file, run it with `psql -d meetup_app < regionseed.sql`
|
||||||
|
|
||||||
|
Test that your regions have been seeded.
|
||||||
|
|
||||||
|
- In a userseed.sql file, write the INSERTS for seven different `users`. Alternatively, write the INSERTS straight into the psql command line. The `region_id` will correspond to the id of one of the previously created regions. You check the region ids by just selecting the regions in psql: `SELECT * FROM regions;`
|
||||||
|
|
||||||
|
Test that your users have been seeded.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Join Queries
|
||||||
|
|
||||||
|
- Select all the regions and join to the regions all associated users. `SELECT * FROM regions . . . `
|
||||||
|
|
||||||
|
EXAMPLE RESULT:
|
||||||
|
|
||||||
|
```
|
||||||
|
id | name | radius | id | name | region_id
|
||||||
|
----+----------------+--------+----+-----------+-----------
|
||||||
|
1 | Alpha Centauri | 8000 | 1 | Mork | 1
|
||||||
|
1 | Alpha Centauri | 8000 | 2 | Mindy | 1
|
||||||
|
2 | Procyon | 20000 | 3 | AlphaGo | 2
|
||||||
|
2 | Procyon | 20000 | 4 | Lee Sedol | 2
|
||||||
|
2 | Procyon | 20000 | 5 | Alvin | 2
|
||||||
|
3 | Black Hole | 600 | 6 | Theodore | 3
|
||||||
|
3 | Black Hole | 600 | 7 | Simon | 3
|
||||||
|
(7 rows)
|
||||||
|
```
|
||||||
|
|
||||||
|
- Refine your result so that you don't get the user's id and region_id displayed. You just want the region id, region name, region radius, and user name.
|
||||||
|
|
||||||
|
EXAMPLE RESULT:
|
||||||
|
|
||||||
|
```
|
||||||
|
id | name | radius | name
|
||||||
|
----+----------------+--------+-----------
|
||||||
|
1 | Alpha Centauri | 8000 | Mork
|
||||||
|
1 | Alpha Centauri | 8000 | Mindy
|
||||||
|
2 | Procyon | 20000 | AlphaGo
|
||||||
|
2 | Procyon | 20000 | Lee Sedol
|
||||||
|
2 | Procyon | 20000 | Alvin
|
||||||
|
3 | Black Hole | 600 | Theodore
|
||||||
|
3 | Black Hole | 600 | Simon
|
||||||
|
(7 rows)
|
||||||
|
```
|
||||||
|
|
||||||
|
- Now we have two columns called `name`. Refine the result further using an alias. Do the same query you did before, but this time, use AS to change the user's `name` column to `user`.
|
||||||
|
|
||||||
|
EXAMPLE RESULT:
|
||||||
|
|
||||||
|
```
|
||||||
|
id | name | radius | user
|
||||||
|
----+----------------+--------+-----------
|
||||||
|
1 | Alpha Centauri | 8000 | Mork
|
||||||
|
1 | Alpha Centauri | 8000 | Mindy
|
||||||
|
2 | Procyon | 20000 | AlphaGo
|
||||||
|
2 | Procyon | 20000 | Lee Sedol
|
||||||
|
2 | Procyon | 20000 | Alvin
|
||||||
|
3 | Black Hole | 600 | Theodore
|
||||||
|
3 | Black Hole | 600 | Simon
|
||||||
|
(7 rows)
|
||||||
|
```
|
||||||
|
|
||||||
|
## BONUS
|
||||||
|
- Find all regions that have more than 1 user
|
||||||
|
- Find all regions with a radius of more than 1000 and less than 3 users
|
||||||
|
|
||||||
|
</br>
|
||||||
|
</br>
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
# SQL Practice - JOINS II
|
||||||
|
|
||||||
|
We will be using the users and regions database, `meetup_app`, to make a many-to-many association.
|
||||||
|
|
||||||
|
|
||||||
|
##Many to Many
|
||||||
|
We want our users to be able to add favorite hobbies. Each user may have many hobbies and each hobby belongs to many users. We will need to set up a table for each of our hobbies and then create a second 'linking table' (also called a 'join table' or 'junction table') where we associate user IDs with hobby IDs.
|
||||||
|
|
||||||
|
- Make a table for `hobbies`. Each hobby should have
|
||||||
|
- Unique ID
|
||||||
|
- Name
|
||||||
|
- Create a table called `user_hobbies`. This will be our linking table
|
||||||
|
- Each entry in this table should have a `user_id` and a `hobby_id` to connect each user with each of their hobbies
|
||||||
|
- Create at least 5 hobbies and associate them with your users
|
||||||
|
- Practice making queries
|
||||||
|
- Display all the users and all the hobbies
|
||||||
|
- Find all users with a given hobby
|
||||||
|
- Order your hobbies by the number of users who have them
|
||||||
|
- Order your users by who has the most hobbies
|
||||||
|
|
||||||
|
|
||||||
|
##**BONUS** - Self Joins
|
||||||
|
We want our users to be able to 'like' each other. We need to keep track of who has liked who and when.
|
||||||
|
|
||||||
|
- Create a `likes` table. Each 'like' should have
|
||||||
|
- A unique ID
|
||||||
|
- An `admirer_id` (the id of the user who did the liking)
|
||||||
|
- A `recipient_id` (the id of the user who was liked)
|
||||||
|
- Practice making queries
|
||||||
|
- Find all likes
|
||||||
|
- Find the user with the most admirers
|
||||||
|
- Find the user who admires the most people
|
||||||
|
- Find all users who like only 1 person
|
||||||
|
- Find all users who like at least 2 people
|
||||||
|
|
||||||
|
##**SUPER BONUS!!!**
|
||||||
|
Try these super hard 'like' queries! Only for the brave!
|
||||||
|
|
||||||
|
- Find all users who mutually admire each other
|
||||||
|
- Find all users who admire someone but no one admires them :(
|
||||||
|
- Find all users who are admired but don't admire anyone yet
|
||||||
|
- Find users who admire less than 3 people and are admired by at least 1 person
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
||||||
|
#
|
||||||
|
# If you find yourself ignoring temporary files generated by your text editor
|
||||||
|
# or operating system, you probably want to add a global ignore instead:
|
||||||
|
# git config --global core.excludesfile '~/.gitignore_global'
|
||||||
|
|
||||||
|
# Ignore bundler config.
|
||||||
|
/.bundle
|
||||||
|
|
||||||
|
# Ignore all logfiles and tempfiles.
|
||||||
|
/log/*
|
||||||
|
!/log/.keep
|
||||||
|
/tmp
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
|
|
||||||
|
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
||||||
|
gem 'rails', '4.2.3'
|
||||||
|
# Use postgresql as the database for Active Record
|
||||||
|
gem 'pg'
|
||||||
|
# Use SCSS for stylesheets
|
||||||
|
gem 'sass-rails', '~> 5.0'
|
||||||
|
# Use Uglifier as compressor for JavaScript assets
|
||||||
|
gem 'uglifier', '>= 1.3.0'
|
||||||
|
# Use CoffeeScript for .coffee assets and views
|
||||||
|
gem 'coffee-rails', '~> 4.1.0'
|
||||||
|
# See https://github.com/rails/execjs#readme for more supported runtimes
|
||||||
|
# gem 'therubyracer', platforms: :ruby
|
||||||
|
|
||||||
|
# Use jquery as the JavaScript library
|
||||||
|
gem 'jquery-rails'
|
||||||
|
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
|
||||||
|
gem 'turbolinks'
|
||||||
|
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
|
||||||
|
gem 'jbuilder', '~> 2.0'
|
||||||
|
# bundle exec rake doc:rails generates the API under doc/api.
|
||||||
|
gem 'sdoc', '~> 0.4.0', group: :doc
|
||||||
|
|
||||||
|
gem 'devise'
|
||||||
|
|
||||||
|
# Use ActiveModel has_secure_password
|
||||||
|
# gem 'bcrypt', '~> 3.1.7'
|
||||||
|
|
||||||
|
# Use Unicorn as the app server
|
||||||
|
# gem 'unicorn'
|
||||||
|
|
||||||
|
# Use Capistrano for deployment
|
||||||
|
# gem 'capistrano-rails', group: :development
|
||||||
|
|
||||||
|
group :development, :test do
|
||||||
|
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
|
||||||
|
gem 'byebug'
|
||||||
|
|
||||||
|
# Access an IRB console on exception pages or by using <%= console %> in views
|
||||||
|
gem 'web-console', '~> 2.0'
|
||||||
|
|
||||||
|
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
|
||||||
|
gem 'spring'
|
||||||
|
end
|
||||||
|
|
||||||
@ -0,0 +1,173 @@
|
|||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
actionmailer (4.2.3)
|
||||||
|
actionpack (= 4.2.3)
|
||||||
|
actionview (= 4.2.3)
|
||||||
|
activejob (= 4.2.3)
|
||||||
|
mail (~> 2.5, >= 2.5.4)
|
||||||
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||||
|
actionpack (4.2.3)
|
||||||
|
actionview (= 4.2.3)
|
||||||
|
activesupport (= 4.2.3)
|
||||||
|
rack (~> 1.6)
|
||||||
|
rack-test (~> 0.6.2)
|
||||||
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||||
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||||
|
actionview (4.2.3)
|
||||||
|
activesupport (= 4.2.3)
|
||||||
|
builder (~> 3.1)
|
||||||
|
erubis (~> 2.7.0)
|
||||||
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||||
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||||
|
activejob (4.2.3)
|
||||||
|
activesupport (= 4.2.3)
|
||||||
|
globalid (>= 0.3.0)
|
||||||
|
activemodel (4.2.3)
|
||||||
|
activesupport (= 4.2.3)
|
||||||
|
builder (~> 3.1)
|
||||||
|
activerecord (4.2.3)
|
||||||
|
activemodel (= 4.2.3)
|
||||||
|
activesupport (= 4.2.3)
|
||||||
|
arel (~> 6.0)
|
||||||
|
activesupport (4.2.3)
|
||||||
|
i18n (~> 0.7)
|
||||||
|
json (~> 1.7, >= 1.7.7)
|
||||||
|
minitest (~> 5.1)
|
||||||
|
thread_safe (~> 0.3, >= 0.3.4)
|
||||||
|
tzinfo (~> 1.1)
|
||||||
|
arel (6.0.3)
|
||||||
|
bcrypt (3.1.11)
|
||||||
|
binding_of_caller (0.7.2)
|
||||||
|
debug_inspector (>= 0.0.1)
|
||||||
|
builder (3.2.2)
|
||||||
|
byebug (8.2.2)
|
||||||
|
coffee-rails (4.1.1)
|
||||||
|
coffee-script (>= 2.2.0)
|
||||||
|
railties (>= 4.0.0, < 5.1.x)
|
||||||
|
coffee-script (2.4.1)
|
||||||
|
coffee-script-source
|
||||||
|
execjs
|
||||||
|
coffee-script-source (1.10.0)
|
||||||
|
concurrent-ruby (1.0.1)
|
||||||
|
debug_inspector (0.0.2)
|
||||||
|
devise (3.5.6)
|
||||||
|
bcrypt (~> 3.0)
|
||||||
|
orm_adapter (~> 0.1)
|
||||||
|
railties (>= 3.2.6, < 5)
|
||||||
|
responders
|
||||||
|
thread_safe (~> 0.1)
|
||||||
|
warden (~> 1.2.3)
|
||||||
|
erubis (2.7.0)
|
||||||
|
execjs (2.6.0)
|
||||||
|
globalid (0.3.6)
|
||||||
|
activesupport (>= 4.1.0)
|
||||||
|
i18n (0.7.0)
|
||||||
|
jbuilder (2.4.1)
|
||||||
|
activesupport (>= 3.0.0, < 5.1)
|
||||||
|
multi_json (~> 1.2)
|
||||||
|
jquery-rails (4.1.1)
|
||||||
|
rails-dom-testing (>= 1, < 3)
|
||||||
|
railties (>= 4.2.0)
|
||||||
|
thor (>= 0.14, < 2.0)
|
||||||
|
json (1.8.3)
|
||||||
|
loofah (2.0.3)
|
||||||
|
nokogiri (>= 1.5.9)
|
||||||
|
mail (2.6.3)
|
||||||
|
mime-types (>= 1.16, < 3)
|
||||||
|
mime-types (2.99.1)
|
||||||
|
mini_portile2 (2.0.0)
|
||||||
|
minitest (5.8.4)
|
||||||
|
multi_json (1.11.2)
|
||||||
|
nokogiri (1.6.7.2)
|
||||||
|
mini_portile2 (~> 2.0.0.rc2)
|
||||||
|
orm_adapter (0.5.0)
|
||||||
|
pg (0.18.4)
|
||||||
|
rack (1.6.4)
|
||||||
|
rack-test (0.6.3)
|
||||||
|
rack (>= 1.0)
|
||||||
|
rails (4.2.3)
|
||||||
|
actionmailer (= 4.2.3)
|
||||||
|
actionpack (= 4.2.3)
|
||||||
|
actionview (= 4.2.3)
|
||||||
|
activejob (= 4.2.3)
|
||||||
|
activemodel (= 4.2.3)
|
||||||
|
activerecord (= 4.2.3)
|
||||||
|
activesupport (= 4.2.3)
|
||||||
|
bundler (>= 1.3.0, < 2.0)
|
||||||
|
railties (= 4.2.3)
|
||||||
|
sprockets-rails
|
||||||
|
rails-deprecated_sanitizer (1.0.3)
|
||||||
|
activesupport (>= 4.2.0.alpha)
|
||||||
|
rails-dom-testing (1.0.7)
|
||||||
|
activesupport (>= 4.2.0.beta, < 5.0)
|
||||||
|
nokogiri (~> 1.6.0)
|
||||||
|
rails-deprecated_sanitizer (>= 1.0.1)
|
||||||
|
rails-html-sanitizer (1.0.3)
|
||||||
|
loofah (~> 2.0)
|
||||||
|
railties (4.2.3)
|
||||||
|
actionpack (= 4.2.3)
|
||||||
|
activesupport (= 4.2.3)
|
||||||
|
rake (>= 0.8.7)
|
||||||
|
thor (>= 0.18.1, < 2.0)
|
||||||
|
rake (11.1.1)
|
||||||
|
rdoc (4.2.2)
|
||||||
|
json (~> 1.4)
|
||||||
|
responders (2.1.2)
|
||||||
|
railties (>= 4.2.0, < 5.1)
|
||||||
|
sass (3.4.21)
|
||||||
|
sass-rails (5.0.4)
|
||||||
|
railties (>= 4.0.0, < 5.0)
|
||||||
|
sass (~> 3.1)
|
||||||
|
sprockets (>= 2.8, < 4.0)
|
||||||
|
sprockets-rails (>= 2.0, < 4.0)
|
||||||
|
tilt (>= 1.1, < 3)
|
||||||
|
sdoc (0.4.1)
|
||||||
|
json (~> 1.7, >= 1.7.7)
|
||||||
|
rdoc (~> 4.0)
|
||||||
|
spring (1.6.4)
|
||||||
|
sprockets (3.5.2)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
rack (> 1, < 3)
|
||||||
|
sprockets-rails (3.0.4)
|
||||||
|
actionpack (>= 4.0)
|
||||||
|
activesupport (>= 4.0)
|
||||||
|
sprockets (>= 3.0.0)
|
||||||
|
thor (0.19.1)
|
||||||
|
thread_safe (0.3.5)
|
||||||
|
tilt (2.0.2)
|
||||||
|
turbolinks (2.5.3)
|
||||||
|
coffee-rails
|
||||||
|
tzinfo (1.2.2)
|
||||||
|
thread_safe (~> 0.1)
|
||||||
|
uglifier (2.7.2)
|
||||||
|
execjs (>= 0.3.0)
|
||||||
|
json (>= 1.8.0)
|
||||||
|
warden (1.2.6)
|
||||||
|
rack (>= 1.0)
|
||||||
|
web-console (2.3.0)
|
||||||
|
activemodel (>= 4.0)
|
||||||
|
binding_of_caller (>= 0.7.2)
|
||||||
|
railties (>= 4.0)
|
||||||
|
sprockets-rails (>= 2.0, < 4.0)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
byebug
|
||||||
|
coffee-rails (~> 4.1.0)
|
||||||
|
devise
|
||||||
|
jbuilder (~> 2.0)
|
||||||
|
jquery-rails
|
||||||
|
pg
|
||||||
|
rails (= 4.2.3)
|
||||||
|
sass-rails (~> 5.0)
|
||||||
|
sdoc (~> 0.4.0)
|
||||||
|
spring
|
||||||
|
turbolinks
|
||||||
|
uglifier (>= 1.3.0)
|
||||||
|
web-console (~> 2.0)
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
1.10.2
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
== README
|
||||||
|
|
||||||
|
This README would normally document whatever steps are necessary to get the
|
||||||
|
application up and running.
|
||||||
|
|
||||||
|
Things you may want to cover:
|
||||||
|
|
||||||
|
* Ruby version
|
||||||
|
|
||||||
|
* System dependencies
|
||||||
|
|
||||||
|
* Configuration
|
||||||
|
|
||||||
|
* Database creation
|
||||||
|
|
||||||
|
* Database initialization
|
||||||
|
|
||||||
|
* How to run the test suite
|
||||||
|
|
||||||
|
* Services (job queues, cache servers, search engines, etc.)
|
||||||
|
|
||||||
|
* Deployment instructions
|
||||||
|
|
||||||
|
* ...
|
||||||
|
|
||||||
|
|
||||||
|
Please feel free to use a different markup language if you do not plan to run
|
||||||
|
<tt>rake doc:app</tt>.
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
||||||
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
||||||
|
|
||||||
|
require File.expand_path('../config/application', __FILE__)
|
||||||
|
|
||||||
|
Rails.application.load_tasks
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
||||||
|
// listed below.
|
||||||
|
//
|
||||||
|
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
||||||
|
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
||||||
|
//
|
||||||
|
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
||||||
|
// compiled file.
|
||||||
|
//
|
||||||
|
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
||||||
|
// about supported directives.
|
||||||
|
//
|
||||||
|
//= require jquery
|
||||||
|
//= require jquery_ujs
|
||||||
|
//= require turbolinks
|
||||||
|
//= require_tree .
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
||||||
|
* listed below.
|
||||||
|
*
|
||||||
|
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
||||||
|
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
||||||
|
*
|
||||||
|
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
||||||
|
* compiled file so the styles you add here take precedence over styles defined in any styles
|
||||||
|
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
||||||
|
* file per style scope.
|
||||||
|
*
|
||||||
|
*= require_tree .
|
||||||
|
*= require_self
|
||||||
|
*/
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
class ApplicationController < ActionController::Base
|
||||||
|
# Prevent CSRF attacks by raising an exception.
|
||||||
|
# For APIs, you may want to use :null_session instead.
|
||||||
|
protect_from_forgery with: :exception
|
||||||
|
end
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
class TweetsController < ApplicationController
|
||||||
|
|
||||||
|
def show
|
||||||
|
@tweet = Tweet.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
class UsersController < ApplicationController
|
||||||
|
|
||||||
|
def index
|
||||||
|
@users = User.all
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
@user = User.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
module ApplicationHelper
|
||||||
|
end
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
class Tweet < ActiveRecord::Base
|
||||||
|
|
||||||
|
belongs_to :user
|
||||||
|
|
||||||
|
end
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
class User < ActiveRecord::Base
|
||||||
|
# Include default devise modules. Others available are:
|
||||||
|
# :confirmable, :lockable, :timeoutable and :omniauthable
|
||||||
|
devise :database_authenticatable, :registerable,
|
||||||
|
:recoverable, :rememberable, :trackable, :validatable
|
||||||
|
|
||||||
|
has_many :tweets
|
||||||
|
end
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tweeter2</title>
|
||||||
|
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
|
||||||
|
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
|
||||||
|
<%= csrf_meta_tags %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<% if notice %>
|
||||||
|
<p class="alert alert-success"><%= notice %></p>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if alert %>
|
||||||
|
<p class="alert alert-danger"><%= alert %></p>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<% if user_signed_in? %>
|
||||||
|
Logged in as <strong><%= current_user.email %></strong>.
|
||||||
|
<%= link_to 'Edit profile', edit_user_registration_path, :class => 'navbar-link' %> |
|
||||||
|
<%= link_to "Logout", destroy_user_session_path, method: :delete, :class => 'navbar-link' %>
|
||||||
|
<% else %>
|
||||||
|
<%= link_to "Sign up", new_user_registration_path, :class => 'navbar-link' %> |
|
||||||
|
<%= link_to "Login", new_user_session_path, :class => 'navbar-link' %>
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<%= yield %>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
<h3><%= @tweet.title %></h3>
|
||||||
|
|
||||||
|
<h1><%= @tweet.content %></h1>
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
<h1> USERS Index </h1>
|
||||||
|
<% @users.each do |user| %>
|
||||||
|
|
||||||
|
<a href="/users/<%= user.id %>"><%= user.email %></a>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<% @user.tweets.each do |tweet| %>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<a href="../tweets/<%= tweet.id %>"><h1 style="font-size: 50px">*~*<%= tweet.title %>*~*</h3></a>
|
||||||
|
<h2 style="font-size: 85px"><%= tweet.content %></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
||||||
|
load Gem.bin_path('bundler', 'bundle')
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
begin
|
||||||
|
load File.expand_path('../spring', __FILE__)
|
||||||
|
rescue LoadError => e
|
||||||
|
raise unless e.message.include?('spring')
|
||||||
|
end
|
||||||
|
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
||||||
|
require_relative '../config/boot'
|
||||||
|
require 'rails/commands'
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
begin
|
||||||
|
load File.expand_path('../spring', __FILE__)
|
||||||
|
rescue LoadError => e
|
||||||
|
raise unless e.message.include?('spring')
|
||||||
|
end
|
||||||
|
require_relative '../config/boot'
|
||||||
|
require 'rake'
|
||||||
|
Rake.application.run
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
require 'pathname'
|
||||||
|
|
||||||
|
# path to your application root.
|
||||||
|
APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
|
||||||
|
|
||||||
|
Dir.chdir APP_ROOT do
|
||||||
|
# This script is a starting point to setup your application.
|
||||||
|
# Add necessary setup steps to this file:
|
||||||
|
|
||||||
|
puts "== Installing dependencies =="
|
||||||
|
system "gem install bundler --conservative"
|
||||||
|
system "bundle check || bundle install"
|
||||||
|
|
||||||
|
# puts "\n== Copying sample files =="
|
||||||
|
# unless File.exist?("config/database.yml")
|
||||||
|
# system "cp config/database.yml.sample config/database.yml"
|
||||||
|
# end
|
||||||
|
|
||||||
|
puts "\n== Preparing database =="
|
||||||
|
system "bin/rake db:setup"
|
||||||
|
|
||||||
|
puts "\n== Removing old logs and tempfiles =="
|
||||||
|
system "rm -f log/*"
|
||||||
|
system "rm -rf tmp/cache"
|
||||||
|
|
||||||
|
puts "\n== Restarting application server =="
|
||||||
|
system "touch tmp/restart.txt"
|
||||||
|
end
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
# This file loads spring without using Bundler, in order to be fast.
|
||||||
|
# It gets overwritten when you run the `spring binstub` command.
|
||||||
|
|
||||||
|
unless defined?(Spring)
|
||||||
|
require 'rubygems'
|
||||||
|
require 'bundler'
|
||||||
|
|
||||||
|
if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m))
|
||||||
|
Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) }
|
||||||
|
gem 'spring', match[1]
|
||||||
|
require 'spring/binstub'
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
# This file is used by Rack-based servers to start the application.
|
||||||
|
|
||||||
|
require ::File.expand_path('../config/environment', __FILE__)
|
||||||
|
run Rails.application
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
require File.expand_path('../boot', __FILE__)
|
||||||
|
|
||||||
|
require 'rails/all'
|
||||||
|
|
||||||
|
# Require the gems listed in Gemfile, including any gems
|
||||||
|
# you've limited to :test, :development, or :production.
|
||||||
|
Bundler.require(*Rails.groups)
|
||||||
|
|
||||||
|
module Tweeter2
|
||||||
|
class Application < Rails::Application
|
||||||
|
# Settings in config/environments/* take precedence over those specified here.
|
||||||
|
# Application configuration should go into files in config/initializers
|
||||||
|
# -- all .rb files in that directory are automatically loaded.
|
||||||
|
|
||||||
|
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
||||||
|
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
||||||
|
# config.time_zone = 'Central Time (US & Canada)'
|
||||||
|
|
||||||
|
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||||
|
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||||
|
# config.i18n.default_locale = :de
|
||||||
|
|
||||||
|
# Do not swallow errors in after_commit/after_rollback callbacks.
|
||||||
|
config.active_record.raise_in_transactional_callbacks = true
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
||||||
|
|
||||||
|
require 'bundler/setup' # Set up gems listed in the Gemfile.
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
# PostgreSQL. Versions 8.2 and up are supported.
|
||||||
|
#
|
||||||
|
# Install the pg driver:
|
||||||
|
# gem install pg
|
||||||
|
# On OS X with Homebrew:
|
||||||
|
# gem install pg -- --with-pg-config=/usr/local/bin/pg_config
|
||||||
|
# On OS X with MacPorts:
|
||||||
|
# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
|
||||||
|
# On Windows:
|
||||||
|
# gem install pg
|
||||||
|
# Choose the win32 build.
|
||||||
|
# Install PostgreSQL and put its /bin directory on your path.
|
||||||
|
#
|
||||||
|
# Configure Using Gemfile
|
||||||
|
# gem 'pg'
|
||||||
|
#
|
||||||
|
default: &default
|
||||||
|
adapter: postgresql
|
||||||
|
encoding: unicode
|
||||||
|
# For details on connection pooling, see rails configuration guide
|
||||||
|
# http://guides.rubyonrails.org/configuring.html#database-pooling
|
||||||
|
pool: 5
|
||||||
|
|
||||||
|
development:
|
||||||
|
<<: *default
|
||||||
|
database: tweeter2_development
|
||||||
|
|
||||||
|
# The specified database role being used to connect to postgres.
|
||||||
|
# To create additional roles in postgres see `$ createuser --help`.
|
||||||
|
# When left blank, postgres will use the default role. This is
|
||||||
|
# the same name as the operating system user that initialized the database.
|
||||||
|
#username: tweeter2
|
||||||
|
|
||||||
|
# The password associated with the postgres role (username).
|
||||||
|
#password:
|
||||||
|
|
||||||
|
# Connect on a TCP socket. Omitted by default since the client uses a
|
||||||
|
# domain socket that doesn't need configuration. Windows does not have
|
||||||
|
# domain sockets, so uncomment these lines.
|
||||||
|
#host: localhost
|
||||||
|
|
||||||
|
# The TCP port the server listens on. Defaults to 5432.
|
||||||
|
# If your server runs on a different port number, change accordingly.
|
||||||
|
#port: 5432
|
||||||
|
|
||||||
|
# Schema search path. The server defaults to $user,public
|
||||||
|
#schema_search_path: myapp,sharedapp,public
|
||||||
|
|
||||||
|
# Minimum log levels, in increasing order:
|
||||||
|
# debug5, debug4, debug3, debug2, debug1,
|
||||||
|
# log, notice, warning, error, fatal, and panic
|
||||||
|
# Defaults to warning.
|
||||||
|
#min_messages: notice
|
||||||
|
|
||||||
|
# Warning: The database defined as "test" will be erased and
|
||||||
|
# re-generated from your development database when you run "rake".
|
||||||
|
# Do not set this db to the same as development or production.
|
||||||
|
test:
|
||||||
|
<<: *default
|
||||||
|
database: tweeter2_test
|
||||||
|
|
||||||
|
# As with config/secrets.yml, you never want to store sensitive information,
|
||||||
|
# like your database password, in your source code. If your source code is
|
||||||
|
# ever seen by anyone, they now have access to your database.
|
||||||
|
#
|
||||||
|
# Instead, provide the password as a unix environment variable when you boot
|
||||||
|
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
|
||||||
|
# for a full rundown on how to provide these environment variables in a
|
||||||
|
# production deployment.
|
||||||
|
#
|
||||||
|
# On Heroku and other platform providers, you may have a full connection URL
|
||||||
|
# available as an environment variable. For example:
|
||||||
|
#
|
||||||
|
# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
|
||||||
|
#
|
||||||
|
# You can use this database configuration with:
|
||||||
|
#
|
||||||
|
# production:
|
||||||
|
# url: <%= ENV['DATABASE_URL'] %>
|
||||||
|
#
|
||||||
|
production:
|
||||||
|
<<: *default
|
||||||
|
database: tweeter2_production
|
||||||
|
username: tweeter2
|
||||||
|
password: <%= ENV['TWEETER2_DATABASE_PASSWORD'] %>
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
# Load the Rails application.
|
||||||
|
require File.expand_path('../application', __FILE__)
|
||||||
|
|
||||||
|
# Initialize the Rails application.
|
||||||
|
Rails.application.initialize!
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
Rails.application.configure do
|
||||||
|
# Settings specified here will take precedence over those in config/application.rb.
|
||||||
|
|
||||||
|
# In the development environment your application's code is reloaded on
|
||||||
|
# every request. This slows down response time but is perfect for development
|
||||||
|
# since you don't have to restart the web server when you make code changes.
|
||||||
|
config.cache_classes = false
|
||||||
|
|
||||||
|
# Do not eager load code on boot.
|
||||||
|
config.eager_load = false
|
||||||
|
|
||||||
|
# Show full error reports and disable caching.
|
||||||
|
config.consider_all_requests_local = true
|
||||||
|
config.action_controller.perform_caching = false
|
||||||
|
|
||||||
|
# Don't care if the mailer can't send.
|
||||||
|
config.action_mailer.raise_delivery_errors = false
|
||||||
|
|
||||||
|
# Print deprecation notices to the Rails logger.
|
||||||
|
config.active_support.deprecation = :log
|
||||||
|
|
||||||
|
# Raise an error on page load if there are pending migrations.
|
||||||
|
config.active_record.migration_error = :page_load
|
||||||
|
|
||||||
|
# Debug mode disables concatenation and preprocessing of assets.
|
||||||
|
# This option may cause significant delays in view rendering with a large
|
||||||
|
# number of complex assets.
|
||||||
|
config.assets.debug = true
|
||||||
|
|
||||||
|
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
|
||||||
|
# yet still be able to expire them through the digest params.
|
||||||
|
config.assets.digest = true
|
||||||
|
|
||||||
|
# Adds additional error checking when serving assets at runtime.
|
||||||
|
# Checks for improperly declared sprockets dependencies.
|
||||||
|
# Raises helpful error messages.
|
||||||
|
config.assets.raise_runtime_errors = true
|
||||||
|
|
||||||
|
# Raises error for missing translations
|
||||||
|
# config.action_view.raise_on_missing_translations = true
|
||||||
|
|
||||||
|
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
||||||
|
end
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
Rails.application.configure do
|
||||||
|
# Settings specified here will take precedence over those in config/application.rb.
|
||||||
|
|
||||||
|
# Code is not reloaded between requests.
|
||||||
|
config.cache_classes = true
|
||||||
|
|
||||||
|
# Eager load code on boot. This eager loads most of Rails and
|
||||||
|
# your application in memory, allowing both threaded web servers
|
||||||
|
# and those relying on copy on write to perform better.
|
||||||
|
# Rake tasks automatically ignore this option for performance.
|
||||||
|
config.eager_load = true
|
||||||
|
|
||||||
|
# Full error reports are disabled and caching is turned on.
|
||||||
|
config.consider_all_requests_local = false
|
||||||
|
config.action_controller.perform_caching = true
|
||||||
|
|
||||||
|
# Enable Rack::Cache to put a simple HTTP cache in front of your application
|
||||||
|
# Add `rack-cache` to your Gemfile before enabling this.
|
||||||
|
# For large-scale production use, consider using a caching reverse proxy like
|
||||||
|
# NGINX, varnish or squid.
|
||||||
|
# config.action_dispatch.rack_cache = true
|
||||||
|
|
||||||
|
# Disable serving static files from the `/public` folder by default since
|
||||||
|
# Apache or NGINX already handles this.
|
||||||
|
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
|
||||||
|
|
||||||
|
# Compress JavaScripts and CSS.
|
||||||
|
config.assets.js_compressor = :uglifier
|
||||||
|
# config.assets.css_compressor = :sass
|
||||||
|
|
||||||
|
# Do not fallback to assets pipeline if a precompiled asset is missed.
|
||||||
|
config.assets.compile = false
|
||||||
|
|
||||||
|
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
|
||||||
|
# yet still be able to expire them through the digest params.
|
||||||
|
config.assets.digest = true
|
||||||
|
|
||||||
|
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
|
||||||
|
|
||||||
|
# Specifies the header that your server uses for sending files.
|
||||||
|
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
|
||||||
|
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
|
||||||
|
|
||||||
|
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
||||||
|
# config.force_ssl = true
|
||||||
|
|
||||||
|
# Use the lowest log level to ensure availability of diagnostic information
|
||||||
|
# when problems arise.
|
||||||
|
config.log_level = :debug
|
||||||
|
|
||||||
|
# Prepend all log lines with the following tags.
|
||||||
|
# config.log_tags = [ :subdomain, :uuid ]
|
||||||
|
|
||||||
|
# Use a different logger for distributed setups.
|
||||||
|
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
|
||||||
|
|
||||||
|
# Use a different cache store in production.
|
||||||
|
# config.cache_store = :mem_cache_store
|
||||||
|
|
||||||
|
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
|
||||||
|
# config.action_controller.asset_host = 'http://assets.example.com'
|
||||||
|
|
||||||
|
# Ignore bad email addresses and do not raise email delivery errors.
|
||||||
|
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||||
|
# config.action_mailer.raise_delivery_errors = false
|
||||||
|
|
||||||
|
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||||
|
# the I18n.default_locale when a translation cannot be found).
|
||||||
|
config.i18n.fallbacks = true
|
||||||
|
|
||||||
|
# Send deprecation notices to registered listeners.
|
||||||
|
config.active_support.deprecation = :notify
|
||||||
|
|
||||||
|
# Use default logging formatter so that PID and timestamp are not suppressed.
|
||||||
|
config.log_formatter = ::Logger::Formatter.new
|
||||||
|
|
||||||
|
# Do not dump schema after migrations.
|
||||||
|
config.active_record.dump_schema_after_migration = false
|
||||||
|
end
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
Rails.application.configure do
|
||||||
|
# Settings specified here will take precedence over those in config/application.rb.
|
||||||
|
|
||||||
|
# The test environment is used exclusively to run your application's
|
||||||
|
# test suite. You never need to work with it otherwise. Remember that
|
||||||
|
# your test database is "scratch space" for the test suite and is wiped
|
||||||
|
# and recreated between test runs. Don't rely on the data there!
|
||||||
|
config.cache_classes = true
|
||||||
|
|
||||||
|
# Do not eager load code on boot. This avoids loading your whole application
|
||||||
|
# just for the purpose of running a single test. If you are using a tool that
|
||||||
|
# preloads Rails for running tests, you may have to set it to true.
|
||||||
|
config.eager_load = false
|
||||||
|
|
||||||
|
# Configure static file server for tests with Cache-Control for performance.
|
||||||
|
config.serve_static_files = true
|
||||||
|
config.static_cache_control = 'public, max-age=3600'
|
||||||
|
|
||||||
|
# Show full error reports and disable caching.
|
||||||
|
config.consider_all_requests_local = true
|
||||||
|
config.action_controller.perform_caching = false
|
||||||
|
|
||||||
|
# Raise exceptions instead of rendering exception templates.
|
||||||
|
config.action_dispatch.show_exceptions = false
|
||||||
|
|
||||||
|
# Disable request forgery protection in test environment.
|
||||||
|
config.action_controller.allow_forgery_protection = false
|
||||||
|
|
||||||
|
# Tell Action Mailer not to deliver emails to the real world.
|
||||||
|
# The :test delivery method accumulates sent emails in the
|
||||||
|
# ActionMailer::Base.deliveries array.
|
||||||
|
config.action_mailer.delivery_method = :test
|
||||||
|
|
||||||
|
# Randomize the order test cases are executed.
|
||||||
|
config.active_support.test_order = :random
|
||||||
|
|
||||||
|
# Print deprecation notices to the stderr.
|
||||||
|
config.active_support.deprecation = :stderr
|
||||||
|
|
||||||
|
# Raises error for missing translations
|
||||||
|
# config.action_view.raise_on_missing_translations = true
|
||||||
|
end
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
|
# Version of your assets, change this if you want to expire all your assets.
|
||||||
|
Rails.application.config.assets.version = '1.0'
|
||||||
|
|
||||||
|
# Add additional assets to the asset load path
|
||||||
|
# Rails.application.config.assets.paths << Emoji.images_path
|
||||||
|
|
||||||
|
# Precompile additional assets.
|
||||||
|
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
||||||
|
# Rails.application.config.assets.precompile += %w( search.js )
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
|
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
||||||
|
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
|
||||||
|
|
||||||
|
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
|
||||||
|
# Rails.backtrace_cleaner.remove_silencers!
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
|
Rails.application.config.action_dispatch.cookies_serializer = :json
|
||||||
@ -0,0 +1,265 @@
|
|||||||
|
# Use this hook to configure devise mailer, warden hooks and so forth.
|
||||||
|
# Many of these configuration options can be set straight in your model.
|
||||||
|
Devise.setup do |config|
|
||||||
|
# The secret key used by Devise. Devise uses this key to generate
|
||||||
|
# random tokens. Changing this key will render invalid all existing
|
||||||
|
# confirmation, reset password and unlock tokens in the database.
|
||||||
|
# Devise will use the `secret_key_base` on Rails 4+ applications as its `secret_key`
|
||||||
|
# by default. You can change it below and use your own secret key.
|
||||||
|
# config.secret_key = '3e7e05066ff20156fbca2f4d6c4525a53544a37ac45d91e72a7440c3f4d514d700466bf4b808da1b6ce8f4b12e2a4e51478c4839b56d73b8a6788c9a65297a1a'
|
||||||
|
|
||||||
|
# ==> Mailer Configuration
|
||||||
|
# Configure the e-mail address which will be shown in Devise::Mailer,
|
||||||
|
# note that it will be overwritten if you use your own mailer class
|
||||||
|
# with default "from" parameter.
|
||||||
|
config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
|
||||||
|
|
||||||
|
# Configure the class responsible to send e-mails.
|
||||||
|
# config.mailer = 'Devise::Mailer'
|
||||||
|
|
||||||
|
# ==> ORM configuration
|
||||||
|
# Load and configure the ORM. Supports :active_record (default) and
|
||||||
|
# :mongoid (bson_ext recommended) by default. Other ORMs may be
|
||||||
|
# available as additional gems.
|
||||||
|
require 'devise/orm/active_record'
|
||||||
|
|
||||||
|
# ==> Configuration for any authentication mechanism
|
||||||
|
# Configure which keys are used when authenticating a user. The default is
|
||||||
|
# just :email. You can configure it to use [:username, :subdomain], so for
|
||||||
|
# authenticating a user, both parameters are required. Remember that those
|
||||||
|
# parameters are used only when authenticating and not when retrieving from
|
||||||
|
# session. If you need permissions, you should implement that in a before filter.
|
||||||
|
# You can also supply a hash where the value is a boolean determining whether
|
||||||
|
# or not authentication should be aborted when the value is not present.
|
||||||
|
# config.authentication_keys = [:email]
|
||||||
|
|
||||||
|
# Configure parameters from the request object used for authentication. Each entry
|
||||||
|
# given should be a request method and it will automatically be passed to the
|
||||||
|
# find_for_authentication method and considered in your model lookup. For instance,
|
||||||
|
# if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
|
||||||
|
# The same considerations mentioned for authentication_keys also apply to request_keys.
|
||||||
|
# config.request_keys = []
|
||||||
|
|
||||||
|
# Configure which authentication keys should be case-insensitive.
|
||||||
|
# These keys will be downcased upon creating or modifying a user and when used
|
||||||
|
# to authenticate or find a user. Default is :email.
|
||||||
|
config.case_insensitive_keys = [:email]
|
||||||
|
|
||||||
|
# Configure which authentication keys should have whitespace stripped.
|
||||||
|
# These keys will have whitespace before and after removed upon creating or
|
||||||
|
# modifying a user and when used to authenticate or find a user. Default is :email.
|
||||||
|
config.strip_whitespace_keys = [:email]
|
||||||
|
|
||||||
|
# Tell if authentication through request.params is enabled. True by default.
|
||||||
|
# It can be set to an array that will enable params authentication only for the
|
||||||
|
# given strategies, for example, `config.params_authenticatable = [:database]` will
|
||||||
|
# enable it only for database (email + password) authentication.
|
||||||
|
# config.params_authenticatable = true
|
||||||
|
|
||||||
|
# Tell if authentication through HTTP Auth is enabled. False by default.
|
||||||
|
# It can be set to an array that will enable http authentication only for the
|
||||||
|
# given strategies, for example, `config.http_authenticatable = [:database]` will
|
||||||
|
# enable it only for database authentication. The supported strategies are:
|
||||||
|
# :database = Support basic authentication with authentication key + password
|
||||||
|
# config.http_authenticatable = false
|
||||||
|
|
||||||
|
# If 401 status code should be returned for AJAX requests. True by default.
|
||||||
|
# config.http_authenticatable_on_xhr = true
|
||||||
|
|
||||||
|
# The realm used in Http Basic Authentication. 'Application' by default.
|
||||||
|
# config.http_authentication_realm = 'Application'
|
||||||
|
|
||||||
|
# It will change confirmation, password recovery and other workflows
|
||||||
|
# to behave the same regardless if the e-mail provided was right or wrong.
|
||||||
|
# Does not affect registerable.
|
||||||
|
# config.paranoid = true
|
||||||
|
|
||||||
|
# By default Devise will store the user in session. You can skip storage for
|
||||||
|
# particular strategies by setting this option.
|
||||||
|
# Notice that if you are skipping storage for all authentication paths, you
|
||||||
|
# may want to disable generating routes to Devise's sessions controller by
|
||||||
|
# passing skip: :sessions to `devise_for` in your config/routes.rb
|
||||||
|
config.skip_session_storage = [:http_auth]
|
||||||
|
|
||||||
|
# By default, Devise cleans up the CSRF token on authentication to
|
||||||
|
# avoid CSRF token fixation attacks. This means that, when using AJAX
|
||||||
|
# requests for sign in and sign up, you need to get a new CSRF token
|
||||||
|
# from the server. You can disable this option at your own risk.
|
||||||
|
# config.clean_up_csrf_token_on_authentication = true
|
||||||
|
|
||||||
|
# ==> Configuration for :database_authenticatable
|
||||||
|
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
|
||||||
|
# using other encryptors, it sets how many times you want the password re-encrypted.
|
||||||
|
#
|
||||||
|
# Limiting the stretches to just one in testing will increase the performance of
|
||||||
|
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
|
||||||
|
# a value less than 10 in other environments. Note that, for bcrypt (the default
|
||||||
|
# encryptor), the cost increases exponentially with the number of stretches (e.g.
|
||||||
|
# a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
|
||||||
|
config.stretches = Rails.env.test? ? 1 : 10
|
||||||
|
|
||||||
|
# Setup a pepper to generate the encrypted password.
|
||||||
|
# config.pepper = '1bbb0b8a870fc04bf84f68a51f5bb13a7ca96ceddfe3e3af8ec02d8ce3b1cc1fa3d342b87883f2f1926a183c14461f6051acde662af99394f02003aa1d249edb'
|
||||||
|
|
||||||
|
# Send a notification email when the user's password is changed
|
||||||
|
# config.send_password_change_notification = false
|
||||||
|
|
||||||
|
# ==> Configuration for :confirmable
|
||||||
|
# A period that the user is allowed to access the website even without
|
||||||
|
# confirming their account. For instance, if set to 2.days, the user will be
|
||||||
|
# able to access the website for two days without confirming their account,
|
||||||
|
# access will be blocked just in the third day. Default is 0.days, meaning
|
||||||
|
# the user cannot access the website without confirming their account.
|
||||||
|
# config.allow_unconfirmed_access_for = 2.days
|
||||||
|
|
||||||
|
# A period that the user is allowed to confirm their account before their
|
||||||
|
# token becomes invalid. For example, if set to 3.days, the user can confirm
|
||||||
|
# their account within 3 days after the mail was sent, but on the fourth day
|
||||||
|
# their account can't be confirmed with the token any more.
|
||||||
|
# Default is nil, meaning there is no restriction on how long a user can take
|
||||||
|
# before confirming their account.
|
||||||
|
# config.confirm_within = 3.days
|
||||||
|
|
||||||
|
# If true, requires any email changes to be confirmed (exactly the same way as
|
||||||
|
# initial account confirmation) to be applied. Requires additional unconfirmed_email
|
||||||
|
# db field (see migrations). Until confirmed, new email is stored in
|
||||||
|
# unconfirmed_email column, and copied to email column on successful confirmation.
|
||||||
|
config.reconfirmable = true
|
||||||
|
|
||||||
|
# Defines which key will be used when confirming an account
|
||||||
|
# config.confirmation_keys = [:email]
|
||||||
|
|
||||||
|
# ==> Configuration for :rememberable
|
||||||
|
# The time the user will be remembered without asking for credentials again.
|
||||||
|
# config.remember_for = 2.weeks
|
||||||
|
|
||||||
|
# Invalidates all the remember me tokens when the user signs out.
|
||||||
|
config.expire_all_remember_me_on_sign_out = true
|
||||||
|
|
||||||
|
# If true, extends the user's remember period when remembered via cookie.
|
||||||
|
# config.extend_remember_period = false
|
||||||
|
|
||||||
|
# Options to be passed to the created cookie. For instance, you can set
|
||||||
|
# secure: true in order to force SSL only cookies.
|
||||||
|
# config.rememberable_options = {}
|
||||||
|
|
||||||
|
# ==> Configuration for :validatable
|
||||||
|
# Range for password length.
|
||||||
|
config.password_length = 8..72
|
||||||
|
|
||||||
|
# Email regex used to validate email formats. It simply asserts that
|
||||||
|
# one (and only one) @ exists in the given string. This is mainly
|
||||||
|
# to give user feedback and not to assert the e-mail validity.
|
||||||
|
# config.email_regexp = /\A[^@]+@[^@]+\z/
|
||||||
|
|
||||||
|
# ==> Configuration for :timeoutable
|
||||||
|
# The time you want to timeout the user session without activity. After this
|
||||||
|
# time the user will be asked for credentials again. Default is 30 minutes.
|
||||||
|
# config.timeout_in = 30.minutes
|
||||||
|
|
||||||
|
# ==> Configuration for :lockable
|
||||||
|
# Defines which strategy will be used to lock an account.
|
||||||
|
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
|
||||||
|
# :none = No lock strategy. You should handle locking by yourself.
|
||||||
|
# config.lock_strategy = :failed_attempts
|
||||||
|
|
||||||
|
# Defines which key will be used when locking and unlocking an account
|
||||||
|
# config.unlock_keys = [:email]
|
||||||
|
|
||||||
|
# Defines which strategy will be used to unlock an account.
|
||||||
|
# :email = Sends an unlock link to the user email
|
||||||
|
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
|
||||||
|
# :both = Enables both strategies
|
||||||
|
# :none = No unlock strategy. You should handle unlocking by yourself.
|
||||||
|
# config.unlock_strategy = :both
|
||||||
|
|
||||||
|
# Number of authentication tries before locking an account if lock_strategy
|
||||||
|
# is failed attempts.
|
||||||
|
# config.maximum_attempts = 20
|
||||||
|
|
||||||
|
# Time interval to unlock the account if :time is enabled as unlock_strategy.
|
||||||
|
# config.unlock_in = 1.hour
|
||||||
|
|
||||||
|
# Warn on the last attempt before the account is locked.
|
||||||
|
# config.last_attempt_warning = true
|
||||||
|
|
||||||
|
# ==> Configuration for :recoverable
|
||||||
|
#
|
||||||
|
# Defines which key will be used when recovering the password for an account
|
||||||
|
# config.reset_password_keys = [:email]
|
||||||
|
|
||||||
|
# Time interval you can reset your password with a reset password key.
|
||||||
|
# Don't put a too small interval or your users won't have the time to
|
||||||
|
# change their passwords.
|
||||||
|
config.reset_password_within = 6.hours
|
||||||
|
|
||||||
|
# When set to false, does not sign a user in automatically after their password is
|
||||||
|
# reset. Defaults to true, so a user is signed in automatically after a reset.
|
||||||
|
# config.sign_in_after_reset_password = true
|
||||||
|
|
||||||
|
# ==> Configuration for :encryptable
|
||||||
|
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
|
||||||
|
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
|
||||||
|
# :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
|
||||||
|
# and :restful_authentication_sha1 (then you should set stretches to 10, and copy
|
||||||
|
# REST_AUTH_SITE_KEY to pepper).
|
||||||
|
#
|
||||||
|
# Require the `devise-encryptable` gem when using anything other than bcrypt
|
||||||
|
# config.encryptor = :sha512
|
||||||
|
|
||||||
|
# ==> Scopes configuration
|
||||||
|
# Turn scoped views on. Before rendering "sessions/new", it will first check for
|
||||||
|
# "users/sessions/new". It's turned off by default because it's slower if you
|
||||||
|
# are using only default views.
|
||||||
|
# config.scoped_views = false
|
||||||
|
|
||||||
|
# Configure the default scope given to Warden. By default it's the first
|
||||||
|
# devise role declared in your routes (usually :user).
|
||||||
|
# config.default_scope = :user
|
||||||
|
|
||||||
|
# Set this configuration to false if you want /users/sign_out to sign out
|
||||||
|
# only the current scope. By default, Devise signs out all scopes.
|
||||||
|
# config.sign_out_all_scopes = true
|
||||||
|
|
||||||
|
# ==> Navigation configuration
|
||||||
|
# Lists the formats that should be treated as navigational. Formats like
|
||||||
|
# :html, should redirect to the sign in page when the user does not have
|
||||||
|
# access, but formats like :xml or :json, should return 401.
|
||||||
|
#
|
||||||
|
# If you have any extra navigational formats, like :iphone or :mobile, you
|
||||||
|
# should add them to the navigational formats lists.
|
||||||
|
#
|
||||||
|
# The "*/*" below is required to match Internet Explorer requests.
|
||||||
|
# config.navigational_formats = ['*/*', :html]
|
||||||
|
|
||||||
|
# The default HTTP method used to sign out a resource. Default is :delete.
|
||||||
|
config.sign_out_via = :delete
|
||||||
|
|
||||||
|
# ==> OmniAuth
|
||||||
|
# Add a new OmniAuth provider. Check the wiki for more information on setting
|
||||||
|
# up on your models and hooks.
|
||||||
|
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
|
||||||
|
|
||||||
|
# ==> Warden configuration
|
||||||
|
# If you want to use other strategies, that are not supported by Devise, or
|
||||||
|
# change the failure app, you can configure them inside the config.warden block.
|
||||||
|
#
|
||||||
|
# config.warden do |manager|
|
||||||
|
# manager.intercept_401 = false
|
||||||
|
# manager.default_strategies(scope: :user).unshift :some_external_strategy
|
||||||
|
# end
|
||||||
|
|
||||||
|
# ==> Mountable engine configurations
|
||||||
|
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
|
||||||
|
# is mountable, there are some extra configurations to be taken into account.
|
||||||
|
# The following options are available, assuming the engine is mounted as:
|
||||||
|
#
|
||||||
|
# mount MyEngine, at: '/my_engine'
|
||||||
|
#
|
||||||
|
# The router that invoked `devise_for`, in the example above, would be:
|
||||||
|
# config.router_name = :my_engine
|
||||||
|
#
|
||||||
|
# When using OmniAuth, Devise cannot automatically set OmniAuth path,
|
||||||
|
# so you need to do it manually. For the users scope, it would be:
|
||||||
|
# config.omniauth_path_prefix = '/my_engine/users/auth'
|
||||||
|
end
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
|
# Configure sensitive parameters which will be filtered from the log file.
|
||||||
|
Rails.application.config.filter_parameters += [:password]
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
|
# Add new inflection rules using the following format. Inflections
|
||||||
|
# are locale specific, and you may define rules for as many different
|
||||||
|
# locales as you wish. All of these examples are active by default:
|
||||||
|
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||||
|
# inflect.plural /^(ox)$/i, '\1en'
|
||||||
|
# inflect.singular /^(ox)en/i, '\1'
|
||||||
|
# inflect.irregular 'person', 'people'
|
||||||
|
# inflect.uncountable %w( fish sheep )
|
||||||
|
# end
|
||||||
|
|
||||||
|
# These inflection rules are supported but not enabled by default:
|
||||||
|
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||||
|
# inflect.acronym 'RESTful'
|
||||||
|
# end
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
|
# Add new mime types for use in respond_to blocks:
|
||||||
|
# Mime::Type.register "text/richtext", :rtf
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
|
Rails.application.config.session_store :cookie_store, key: '_tweeter2_session'
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
|
# This file contains settings for ActionController::ParamsWrapper which
|
||||||
|
# is enabled by default.
|
||||||
|
|
||||||
|
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
||||||
|
ActiveSupport.on_load(:action_controller) do
|
||||||
|
wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
|
||||||
|
end
|
||||||
|
|
||||||
|
# To enable root element in JSON for ActiveRecord objects.
|
||||||
|
# ActiveSupport.on_load(:active_record) do
|
||||||
|
# self.include_root_in_json = true
|
||||||
|
# end
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
|
||||||
|
|
||||||
|
en:
|
||||||
|
devise:
|
||||||
|
confirmations:
|
||||||
|
confirmed: "Your email address has been successfully confirmed."
|
||||||
|
send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
|
||||||
|
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
|
||||||
|
failure:
|
||||||
|
already_authenticated: "You are already signed in."
|
||||||
|
inactive: "Your account is not activated yet."
|
||||||
|
invalid: "Invalid %{authentication_keys} or password."
|
||||||
|
locked: "Your account is locked."
|
||||||
|
last_attempt: "You have one more attempt before your account is locked."
|
||||||
|
not_found_in_database: "Invalid %{authentication_keys} or password."
|
||||||
|
timeout: "Your session expired. Please sign in again to continue."
|
||||||
|
unauthenticated: "You need to sign in or sign up before continuing."
|
||||||
|
unconfirmed: "You have to confirm your email address before continuing."
|
||||||
|
mailer:
|
||||||
|
confirmation_instructions:
|
||||||
|
subject: "Confirmation instructions"
|
||||||
|
reset_password_instructions:
|
||||||
|
subject: "Reset password instructions"
|
||||||
|
unlock_instructions:
|
||||||
|
subject: "Unlock instructions"
|
||||||
|
password_change:
|
||||||
|
subject: "Password Changed"
|
||||||
|
omniauth_callbacks:
|
||||||
|
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
|
||||||
|
success: "Successfully authenticated from %{kind} account."
|
||||||
|
passwords:
|
||||||
|
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
|
||||||
|
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
|
||||||
|
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||||
|
updated: "Your password has been changed successfully. You are now signed in."
|
||||||
|
updated_not_active: "Your password has been changed successfully."
|
||||||
|
registrations:
|
||||||
|
destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
|
||||||
|
signed_up: "Welcome! You have signed up successfully."
|
||||||
|
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
|
||||||
|
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
|
||||||
|
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
|
||||||
|
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
|
||||||
|
updated: "Your account has been updated successfully."
|
||||||
|
sessions:
|
||||||
|
signed_in: "Signed in successfully."
|
||||||
|
signed_out: "Signed out successfully."
|
||||||
|
already_signed_out: "Signed out successfully."
|
||||||
|
unlocks:
|
||||||
|
send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
|
||||||
|
send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
|
||||||
|
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
|
||||||
|
errors:
|
||||||
|
messages:
|
||||||
|
already_confirmed: "was already confirmed, please try signing in"
|
||||||
|
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
|
||||||
|
expired: "has expired, please request a new one"
|
||||||
|
not_found: "not found"
|
||||||
|
not_locked: "was not locked"
|
||||||
|
not_saved:
|
||||||
|
one: "1 error prohibited this %{resource} from being saved:"
|
||||||
|
other: "%{count} errors prohibited this %{resource} from being saved:"
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
# Files in the config/locales directory are used for internationalization
|
||||||
|
# and are automatically loaded by Rails. If you want to use locales other
|
||||||
|
# than English, add the necessary files in this directory.
|
||||||
|
#
|
||||||
|
# To use the locales, use `I18n.t`:
|
||||||
|
#
|
||||||
|
# I18n.t 'hello'
|
||||||
|
#
|
||||||
|
# In views, this is aliased to just `t`:
|
||||||
|
#
|
||||||
|
# <%= t('hello') %>
|
||||||
|
#
|
||||||
|
# To use a different locale, set it with `I18n.locale`:
|
||||||
|
#
|
||||||
|
# I18n.locale = :es
|
||||||
|
#
|
||||||
|
# This would use the information in config/locales/es.yml.
|
||||||
|
#
|
||||||
|
# To learn more, please read the Rails Internationalization guide
|
||||||
|
# available at http://guides.rubyonrails.org/i18n.html.
|
||||||
|
|
||||||
|
en:
|
||||||
|
hello: "Hello world"
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
Rails.application.routes.draw do
|
||||||
|
|
||||||
|
devise_for :users
|
||||||
|
resources :users
|
||||||
|
resources :tweets
|
||||||
|
|
||||||
|
root to: 'users#index'
|
||||||
|
# The priority is based upon order of creation: first created -> highest priority.
|
||||||
|
# See how all your routes lay out with "rake routes".
|
||||||
|
|
||||||
|
# You can have the root of your site routed with "root"
|
||||||
|
# root 'welcome#index'
|
||||||
|
|
||||||
|
# Example of regular route:
|
||||||
|
# get 'products/:id' => 'catalog#view'
|
||||||
|
|
||||||
|
# Example of named route that can be invoked with purchase_url(id: product.id)
|
||||||
|
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
|
||||||
|
|
||||||
|
# Example resource route (maps HTTP verbs to controller actions automatically):
|
||||||
|
# resources :products
|
||||||
|
|
||||||
|
# Example resource route with options:
|
||||||
|
# resources :products do
|
||||||
|
# member do
|
||||||
|
# get 'short'
|
||||||
|
# post 'toggle'
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# collection do
|
||||||
|
# get 'sold'
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Example resource route with sub-resources:
|
||||||
|
# resources :products do
|
||||||
|
# resources :comments, :sales
|
||||||
|
# resource :seller
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Example resource route with more complex sub-resources:
|
||||||
|
# resources :products do
|
||||||
|
# resources :comments
|
||||||
|
# resources :sales do
|
||||||
|
# get 'recent', on: :collection
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Example resource route with concerns:
|
||||||
|
# concern :toggleable do
|
||||||
|
# post 'toggle'
|
||||||
|
# end
|
||||||
|
# resources :posts, concerns: :toggleable
|
||||||
|
# resources :photos, concerns: :toggleable
|
||||||
|
|
||||||
|
# Example resource route within a namespace:
|
||||||
|
# namespace :admin do
|
||||||
|
# # Directs /admin/products/* to Admin::ProductsController
|
||||||
|
# # (app/controllers/admin/products_controller.rb)
|
||||||
|
# resources :products
|
||||||
|
# end
|
||||||
|
end
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
|
# Your secret key is used for verifying the integrity of signed cookies.
|
||||||
|
# If you change this key, all old signed cookies will become invalid!
|
||||||
|
|
||||||
|
# Make sure the secret is at least 30 characters and all random,
|
||||||
|
# no regular words or you'll be exposed to dictionary attacks.
|
||||||
|
# You can use `rake secret` to generate a secure secret key.
|
||||||
|
|
||||||
|
# Make sure the secrets in this file are kept private
|
||||||
|
# if you're sharing your code publicly.
|
||||||
|
|
||||||
|
development:
|
||||||
|
secret_key_base: 6d76b1889cae8adac7e7411216407fd5448382fc155218a3ce77edf22e8d0050a16a595d789bfbb7d04d0f725b1f47ae6c64b0502ead607c4fab09443c0d00c3
|
||||||
|
|
||||||
|
test:
|
||||||
|
secret_key_base: 586e665aa8eec93ec10f8bcffcd420c83c24940c44096bd9f3fd1c4a8ed674431bb55caaf49d57df092b1748556a3031bf72565ffdcb574bb9c8a978b9c605d2
|
||||||
|
|
||||||
|
# Do not keep production secrets in the repository,
|
||||||
|
# instead read values from the environment.
|
||||||
|
production:
|
||||||
|
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
class DeviseCreateUsers < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table(:users) do |t|
|
||||||
|
## Database authenticatable
|
||||||
|
t.string :email, null: false, default: ""
|
||||||
|
t.string :encrypted_password, null: false, default: ""
|
||||||
|
|
||||||
|
## Recoverable
|
||||||
|
t.string :reset_password_token
|
||||||
|
t.datetime :reset_password_sent_at
|
||||||
|
|
||||||
|
## Rememberable
|
||||||
|
t.datetime :remember_created_at
|
||||||
|
|
||||||
|
## Trackable
|
||||||
|
t.integer :sign_in_count, default: 0, null: false
|
||||||
|
t.datetime :current_sign_in_at
|
||||||
|
t.datetime :last_sign_in_at
|
||||||
|
t.inet :current_sign_in_ip
|
||||||
|
t.inet :last_sign_in_ip
|
||||||
|
|
||||||
|
## Confirmable
|
||||||
|
# t.string :confirmation_token
|
||||||
|
# t.datetime :confirmed_at
|
||||||
|
# t.datetime :confirmation_sent_at
|
||||||
|
# t.string :unconfirmed_email # Only if using reconfirmable
|
||||||
|
|
||||||
|
## Lockable
|
||||||
|
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
|
||||||
|
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
||||||
|
# t.datetime :locked_at
|
||||||
|
|
||||||
|
|
||||||
|
t.timestamps null: false
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :users, :email, unique: true
|
||||||
|
add_index :users, :reset_password_token, unique: true
|
||||||
|
# add_index :users, :confirmation_token, unique: true
|
||||||
|
# add_index :users, :unlock_token, unique: true
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
class CreateTweets < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :tweets do |t|
|
||||||
|
t.string :title
|
||||||
|
t.text :content
|
||||||
|
t.references :user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
# encoding: UTF-8
|
||||||
|
# This file is auto-generated from the current state of the database. Instead
|
||||||
|
# of editing this file, please use the migrations feature of Active Record to
|
||||||
|
# incrementally modify your database, and then regenerate this schema definition.
|
||||||
|
#
|
||||||
|
# Note that this schema.rb definition is the authoritative source for your
|
||||||
|
# database schema. If you need to create the application database on another
|
||||||
|
# system, you should be using db:schema:load, not running all the migrations
|
||||||
|
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||||
|
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||||
|
#
|
||||||
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
|
ActiveRecord::Schema.define(version: 20160321184431) do
|
||||||
|
|
||||||
|
# These are extensions that must be enabled in order to support this database
|
||||||
|
enable_extension "plpgsql"
|
||||||
|
|
||||||
|
create_table "tweets", force: :cascade do |t|
|
||||||
|
t.string "title"
|
||||||
|
t.text "content"
|
||||||
|
t.integer "user_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "users", force: :cascade do |t|
|
||||||
|
t.string "email", default: "", null: false
|
||||||
|
t.string "encrypted_password", default: "", null: false
|
||||||
|
t.string "reset_password_token"
|
||||||
|
t.datetime "reset_password_sent_at"
|
||||||
|
t.datetime "remember_created_at"
|
||||||
|
t.integer "sign_in_count", default: 0, null: false
|
||||||
|
t.datetime "current_sign_in_at"
|
||||||
|
t.datetime "last_sign_in_at"
|
||||||
|
t.inet "current_sign_in_ip"
|
||||||
|
t.inet "last_sign_in_ip"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
|
||||||
|
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
|
||||||
|
|
||||||
|
end
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
# This file should contain all the record creation needed to seed the database with its default values.
|
||||||
|
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
|
||||||
|
# Mayor.create(name: 'Emanuel', city: cities.first)
|
||||||
|
|
||||||
|
Tweet.create({
|
||||||
|
title: "Test tweet3",
|
||||||
|
content: "Hehe! That's so funny :) :) :)",
|
||||||
|
user_id: 1
|
||||||
|
})
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>The page you were looking for doesn't exist (404)</title>
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #EFEFEF;
|
||||||
|
color: #2E2F30;
|
||||||
|
text-align: center;
|
||||||
|
font-family: arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dialog {
|
||||||
|
width: 95%;
|
||||||
|
max-width: 33em;
|
||||||
|
margin: 4em auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dialog > div {
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
border-right-color: #999;
|
||||||
|
border-left-color: #999;
|
||||||
|
border-bottom-color: #BBB;
|
||||||
|
border-top: #B00100 solid 4px;
|
||||||
|
border-top-left-radius: 9px;
|
||||||
|
border-top-right-radius: 9px;
|
||||||
|
background-color: white;
|
||||||
|
padding: 7px 12% 0;
|
||||||
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 100%;
|
||||||
|
color: #730E15;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dialog > p {
|
||||||
|
margin: 0 0 1em;
|
||||||
|
padding: 1em;
|
||||||
|
background-color: #F7F7F7;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
border-right-color: #999;
|
||||||
|
border-left-color: #999;
|
||||||
|
border-bottom-color: #999;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
border-top-color: #DADADA;
|
||||||
|
color: #666;
|
||||||
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- This file lives in public/404.html -->
|
||||||
|
<div class="dialog">
|
||||||
|
<div>
|
||||||
|
<h1>The page you were looking for doesn't exist.</h1>
|
||||||
|
<p>You may have mistyped the address or the page may have moved.</p>
|
||||||
|
</div>
|
||||||
|
<p>If you are the application owner check the logs for more information.</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>The change you wanted was rejected (422)</title>
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #EFEFEF;
|
||||||
|
color: #2E2F30;
|
||||||
|
text-align: center;
|
||||||
|
font-family: arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dialog {
|
||||||
|
width: 95%;
|
||||||
|
max-width: 33em;
|
||||||
|
margin: 4em auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dialog > div {
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
border-right-color: #999;
|
||||||
|
border-left-color: #999;
|
||||||
|
border-bottom-color: #BBB;
|
||||||
|
border-top: #B00100 solid 4px;
|
||||||
|
border-top-left-radius: 9px;
|
||||||
|
border-top-right-radius: 9px;
|
||||||
|
background-color: white;
|
||||||
|
padding: 7px 12% 0;
|
||||||
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 100%;
|
||||||
|
color: #730E15;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dialog > p {
|
||||||
|
margin: 0 0 1em;
|
||||||
|
padding: 1em;
|
||||||
|
background-color: #F7F7F7;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
border-right-color: #999;
|
||||||
|
border-left-color: #999;
|
||||||
|
border-bottom-color: #999;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
border-top-color: #DADADA;
|
||||||
|
color: #666;
|
||||||
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- This file lives in public/422.html -->
|
||||||
|
<div class="dialog">
|
||||||
|
<div>
|
||||||
|
<h1>The change you wanted was rejected.</h1>
|
||||||
|
<p>Maybe you tried to change something you didn't have access to.</p>
|
||||||
|
</div>
|
||||||
|
<p>If you are the application owner check the logs for more information.</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>We're sorry, but something went wrong (500)</title>
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #EFEFEF;
|
||||||
|
color: #2E2F30;
|
||||||
|
text-align: center;
|
||||||
|
font-family: arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dialog {
|
||||||
|
width: 95%;
|
||||||
|
max-width: 33em;
|
||||||
|
margin: 4em auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dialog > div {
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
border-right-color: #999;
|
||||||
|
border-left-color: #999;
|
||||||
|
border-bottom-color: #BBB;
|
||||||
|
border-top: #B00100 solid 4px;
|
||||||
|
border-top-left-radius: 9px;
|
||||||
|
border-top-right-radius: 9px;
|
||||||
|
background-color: white;
|
||||||
|
padding: 7px 12% 0;
|
||||||
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 100%;
|
||||||
|
color: #730E15;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dialog > p {
|
||||||
|
margin: 0 0 1em;
|
||||||
|
padding: 1em;
|
||||||
|
background-color: #F7F7F7;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
border-right-color: #999;
|
||||||
|
border-left-color: #999;
|
||||||
|
border-bottom-color: #999;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
border-top-color: #DADADA;
|
||||||
|
color: #666;
|
||||||
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- This file lives in public/500.html -->
|
||||||
|
<div class="dialog">
|
||||||
|
<div>
|
||||||
|
<h1>We're sorry, but something went wrong.</h1>
|
||||||
|
</div>
|
||||||
|
<p>If you are the application owner check the logs for more information.</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
|
||||||
|
#
|
||||||
|
# To ban all spiders from the entire site uncomment the next two lines:
|
||||||
|
# User-agent: *
|
||||||
|
# Disallow: /
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||||
|
|
||||||
|
# This model initially had no columns defined. If you add columns to the
|
||||||
|
# model remove the '{}' from the fixture names and add the columns immediately
|
||||||
|
# below each fixture, per the syntax in the comments below
|
||||||
|
#
|
||||||
|
one: {}
|
||||||
|
# column: value
|
||||||
|
#
|
||||||
|
two: {}
|
||||||
|
# column: value
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class UserTest < ActiveSupport::TestCase
|
||||||
|
# test "the truth" do
|
||||||
|
# assert true
|
||||||
|
# end
|
||||||
|
end
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
ENV['RAILS_ENV'] ||= 'test'
|
||||||
|
require File.expand_path('../../config/environment', __FILE__)
|
||||||
|
require 'rails/test_help'
|
||||||
|
|
||||||
|
class ActiveSupport::TestCase
|
||||||
|
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
|
||||||
|
fixtures :all
|
||||||
|
|
||||||
|
# Add more helper methods to be used by all tests here...
|
||||||
|
end
|
||||||
@ -0,0 +1,122 @@
|
|||||||
|
# TWEET_R AGAIN
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Oh goody.
|
||||||
|
</br>
|
||||||
|
|
||||||
|
We are going to build on the Tweet_r app that you started in the weekend, but this time we will have users. Users will be related to tweets via a **one-to-many association**. The Users model and authentication will be handled with the Devise gem. For this project, you can either:
|
||||||
|
|
||||||
|
- Make the Tweet_r app again with users in mind. (Tweets will not need an index page this time). Recommended.
|
||||||
|
- Adjust the Tweet_r app you previously made. In this case you will need to run a migration that adds references to your Tweet model.
|
||||||
|
|
||||||
|
|
||||||
|
### APP - USER STORIES
|
||||||
|
|
||||||
|
- Your app should have signup, login, logout functionality.
|
||||||
|
- There should be an index of users, visible to anyone. You should be able to click on a user and go to the show page.
|
||||||
|
- If you look at a user's show page, you should see the user's tweets.
|
||||||
|
- If you click on a user's tweet, you should go to the tweet's show page.
|
||||||
|
- If a user logs in / signs up, that user should be able to post tweets to his or her own page.
|
||||||
|
|
||||||
|
|
||||||
|
### MODELS
|
||||||
|
You will need:
|
||||||
|
|
||||||
|
- **User**. Set up your app to use Devise, and make your User with Devise. See the class notes.
|
||||||
|
- **Tweet**. Remember that the Tweet migration will need a foreign key to reference User. Your Tweet migration file could look exactly like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
class CreateTweets < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :tweets do |t|
|
||||||
|
t.string :title
|
||||||
|
t.text :content
|
||||||
|
t.references :user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
After you run the migration, check out `schema.rb` and see that the migration made a `user_id` column with type `integer`.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
RELATIONSHIP:
|
||||||
|
|
||||||
|
There is a one-to-many relationship between User and Tweet.
|
||||||
|
|
||||||
|
- A User `has_many :tweets`
|
||||||
|
|
||||||
|
- A Tweet `belongs_to :user`
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### ROUTES
|
||||||
|
|
||||||
|
The Devise gem requires that you specify a root, so lets set `root to: 'users#index'`
|
||||||
|
|
||||||
|
```
|
||||||
|
QUESTION
|
||||||
|
Considering that you made the User with Devise, do you need to set resources to get RESTful routes for your User? Have a think about it, or better yet, experiment in order answer the question.
|
||||||
|
```
|
||||||
|
|
||||||
|
The answer is: Yes, you will want to set `resources :users` so that we can access a users index route, show route, etc. By the same token we will also want to make our own Users controller . . . continued below.
|
||||||
|
|
||||||
|
There is no real need to use nested resources in this app, but it would be good practise for a bonus.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### CONTROLLERS
|
||||||
|
Don't worry about full CRUD. Just get it so that you can see the Tweets associated with particular Users.
|
||||||
|
|
||||||
|
```
|
||||||
|
QUESTION
|
||||||
|
Considering that you made the User with Devise, should you even create a Users controller? How can we get our actions for our RESTful routes? Have a think, or better yet experiment to answer the question.
|
||||||
|
```
|
||||||
|
|
||||||
|
The answer is: Devise doesn't give us our restful routes. We can go ahead and make our own Users controller to do this, and it's safe to do so. Make an index and a show to begin with.
|
||||||
|
|
||||||
|
Later, there will need to be a way to make new Users and new Tweets associated with a User, and a way to see individual Tweets.
|
||||||
|
|
||||||
|
|
||||||
|
### SEEDING AND VIEWS
|
||||||
|
|
||||||
|
You don't have to seed Users thanks to Devise, but seed a Tweet or two using `seeds.rb`. Use a user's id as the `user_id`.
|
||||||
|
|
||||||
|
### Good luck!
|
||||||
|
|
||||||
|
</br>
|
||||||
|
|
||||||
|
|
||||||
|
# SUGGESTED SEQUENCE OF EVENTS:
|
||||||
|
|
||||||
|
1. Set up a User with Devise, add resources to routes, and index/show actions to a Users controller
|
||||||
|
2. Show all users on the users index page
|
||||||
|
3. Click on a user and go to the users show page
|
||||||
|
4. Create a migration for Tweet including a reference to User
|
||||||
|
5. Seed a couple'a tweets, using a user id as the user_id
|
||||||
|
6. Display the tweets on the user's show page
|
||||||
|
7. Make it so that when you click on a Tweet, you go to its show page
|
||||||
|
8. Make it so a user can make a new Tweet
|
||||||
|
|
||||||
|
|
||||||
|
### BONUS
|
||||||
|
|
||||||
|
Use nested resources to display your users' tweets
|
||||||
|
|
||||||
|
Add a third model, `Comment`. A User should be able to make a comment on a tweet. (More complicated than it sounds).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||