Skip to content
Open

0b1 #68

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@
/yarn-error.log

.byebug_history
.idea/*
.DS_Store

44 changes: 30 additions & 14 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,37 @@ source 'https://rubygems.org'

ruby File.read('.ruby-version').chomp

gem 'byebug', platforms: [:mri, :mingw, :x64_mingw], group: [:development, :test]
gem 'capybara', group: [:development, :test]
gem 'coffee-rails'
gem 'devise'
gem 'jbuilder'
gem 'listen', group: :development
gem 'rails', '~> 7.0.3'
gem 'pg'
gem 'pry-rails'
gem 'puma'
gem 'rails', '~> 7.0.3'
gem 'rspec-rails'
gem 'sass-rails'
gem 'selenium-webdriver', group: [:development, :test]
gem 'spring', group: :development
gem 'turbolinks'
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem 'coffee-rails'
gem 'uglifier'
gem 'web-console', group: :development
gem 'turbolinks'
gem 'jbuilder'
gem 'devise'

group :development, :test do
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'capybara'
gem 'selenium-webdriver'
gem 'webdrivers'
gem 'rspec-rails'
gem 'database_cleaner-active_record'
gem 'factory_bot_rails'
gem 'webmock'
end

group :development do
gem 'listen'
gem 'spring'
gem 'web-console'
gem 'pry-rails'
end

group :test do
gem 'simplecov', require: false # Optional, for test coverage
gem 'shoulda-matchers' # Optional, for simplified model specs
end

gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
37 changes: 37 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ GEM
addressable (2.8.1)
public_suffix (>= 2.0.2, < 6.0)
bcrypt (3.1.18)
bigdecimal (3.1.8)
bindex (0.8.1)
builder (3.2.4)
byebug (11.1.3)
Expand All @@ -91,7 +92,14 @@ GEM
execjs
coffee-script-source (1.12.2)
concurrent-ruby (1.1.10)
crack (1.0.0)
bigdecimal
rexml
crass (1.0.6)
database_cleaner-active_record (2.2.0)
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
devise (4.8.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
Expand All @@ -100,11 +108,18 @@ GEM
warden (~> 1.2.3)
diff-lcs (1.5.0)
digest (3.1.0)
docile (1.4.0)
erubi (1.11.0)
execjs (2.8.1)
factory_bot (6.4.6)
activesupport (>= 5.0.0)
factory_bot_rails (6.4.3)
factory_bot (~> 6.4)
railties (>= 5.0.0)
ffi (1.15.5)
globalid (1.0.0)
activesupport (>= 5.0)
hashdiff (1.1.0)
i18n (1.12.0)
concurrent-ruby (~> 1.0)
jbuilder (2.11.5)
Expand Down Expand Up @@ -224,6 +239,14 @@ GEM
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
shoulda-matchers (6.2.0)
activesupport (>= 5.2.0)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.4)
spring (4.1.0)
sprockets (4.1.1)
concurrent-ruby (~> 1.0)
Expand All @@ -250,6 +273,14 @@ GEM
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
webdrivers (5.3.1)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (~> 4.0, < 4.11)
webmock (3.23.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
websocket (1.2.9)
websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0)
Expand All @@ -265,7 +296,9 @@ DEPENDENCIES
byebug
capybara
coffee-rails
database_cleaner-active_record
devise
factory_bot_rails
jbuilder
listen
pg
Expand All @@ -275,11 +308,15 @@ DEPENDENCIES
rspec-rails
sass-rails
selenium-webdriver
shoulda-matchers
simplecov
spring
turbolinks
tzinfo-data
uglifier
web-console
webdrivers
webmock

RUBY VERSION
ruby 3.1.2p20
Expand Down
7 changes: 7 additions & 0 deletions app/controllers/interesting_stories_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class InterestingStoriesController < ApplicationController
before_action :authenticate_user!

def index
@interesting_stories = InterestingStory.includes(:story, :user).all
end
end
32 changes: 32 additions & 0 deletions app/controllers/stories_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# app/controllers/stories_controller.rb
class StoriesController < ApplicationController
before_action :authenticate_user!

def index
@stories = Story.fetch_top_stories.take(10).map { |story_id| Story.fetch_story_details(story_id) }
end

def mark_interesting
story_details = Story.fetch_story_details(params[:id].to_i)
@story = Story.find_or_initialize_by(story_id: story_details["id"])
@story.update(story_params(story_details))

InterestingStory.create(user: current_user, story: @story)

redirect_to interesting_stories_path, notice: 'Story marked as interesting.'
end

private

def story_params(details)
{
title: details["title"],
url: details["url"],
by: details["by"],
score: details["score"],
time: Time.at(details["time"]),
descendants: details["descendants"],
story_type: details["type"]
}
end
end
6 changes: 6 additions & 0 deletions app/models/interesting_story.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# app/models/interesting_story.rb
class InterestingStory < ApplicationRecord
belongs_to :user
belongs_to :story
validates :user_id, uniqueness: { scope: :story_id, message: "has already marked this story as interesting" }
end
20 changes: 20 additions & 0 deletions app/models/story.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# app/models/story.rb
require 'net/http'
require 'json'

class Story < ApplicationRecord
has_many :interesting_stories
has_many :users, through: :interesting_stories

def self.fetch_top_stories
url = URI.parse('https://hacker-news.firebaseio.com/v0/topstories.json')
response = Net::HTTP.get_response(url)
JSON.parse(response.body)
end

def self.fetch_story_details(story_id)
url = URI.parse("https://hacker-news.firebaseio.com/v0/item/#{story_id}.json")
response = Net::HTTP.get_response(url)
JSON.parse(response.body)
end
end
16 changes: 16 additions & 0 deletions app/views/devise/confirmations/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h2>Resend confirmation instructions</h2>

<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
</div>

<div class="actions">
<%= f.submit "Resend confirmation instructions" %>
</div>
<% end %>

<%= render "devise/shared/links" %>
5 changes: 5 additions & 0 deletions app/views/devise/mailer/confirmation_instructions.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<p>Welcome <%= @email %>!</p>

<p>You can confirm your account email through the link below:</p>

<p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>
7 changes: 7 additions & 0 deletions app/views/devise/mailer/email_changed.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<p>Hello <%= @email %>!</p>

<% if @resource.try(:unconfirmed_email?) %>
<p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p>
<% else %>
<p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p>
<% end %>
3 changes: 3 additions & 0 deletions app/views/devise/mailer/password_change.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<p>Hello <%= @resource.email %>!</p>

<p>We're contacting you to notify you that your password has been changed.</p>
8 changes: 8 additions & 0 deletions app/views/devise/mailer/reset_password_instructions.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<p>Hello <%= @resource.email %>!</p>

<p>Someone has requested a link to change your password. You can do this through the link below.</p>

<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>

<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>
7 changes: 7 additions & 0 deletions app/views/devise/mailer/unlock_instructions.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<p>Hello <%= @resource.email %>!</p>

<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>

<p>Click the link below to unlock your account:</p>

<p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>
25 changes: 25 additions & 0 deletions app/views/devise/passwords/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<h2>Change your password</h2>

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<%= f.hidden_field :reset_password_token %>

<div class="field">
<%= f.label :password, "New password" %><br />
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em><br />
<% end %>
<%= f.password_field :password, autofocus: true, autocomplete: "new-password" %>
</div>

<div class="field">
<%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>

<div class="actions">
<%= f.submit "Change my password" %>
</div>
<% end %>

<%= render "devise/shared/links" %>
16 changes: 16 additions & 0 deletions app/views/devise/passwords/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h2>Forgot your password?</h2>

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>

<div class="actions">
<%= f.submit "Send me reset password instructions" %>
</div>
<% end %>

<%= render "devise/shared/links" %>
43 changes: 43 additions & 0 deletions app/views/devise/registrations/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>

<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>

<div class="field">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, autocomplete: "new-password" %>
<% if @minimum_password_length %>
<br />
<em><%= @minimum_password_length %> characters minimum</em>
<% end %>
</div>

<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>

<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "current-password" %>
</div>

<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>

<h3>Cancel my account</h3>

<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>

<%= link_to "Back", :back %>
29 changes: 29 additions & 0 deletions app/views/devise/registrations/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>

<div class="field">
<%= f.label :password %>
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>

<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>

<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>

<%= render "devise/shared/links" %>
Loading