Added recipe search; bumped gems and ruby version

This commit is contained in:
Dan Elbert 2017-03-29 16:52:59 -05:00
parent 977e0e8d6a
commit afc2793375
9 changed files with 237 additions and 175 deletions

View File

@ -1 +1 @@
2.3.1
2.4.1

View File

@ -1,4 +1,4 @@
FROM phusion/passenger-ruby23:latest
FROM phusion/passenger-ruby24:latest
# Use baseimage-docker's init process.
CMD ["/sbin/my_init"]

14
Gemfile
View File

@ -1,8 +1,8 @@
source 'https://rubygems.org'
gem 'rails', '5.0.0'
gem 'rails', '5.0.2'
gem 'sqlite3'
gem 'pg', '~> 0.18.4'
gem 'pg', '~> 0.20.0'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
@ -12,11 +12,11 @@ gem 'puma'
gem 'therubyracer', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails', '~> 4.1.1'
gem 'bootstrap-sass', '~> 3.3.6'
gem 'kaminari', '~> 0.17.0'
gem 'turbolinks', '~> 5.0.0'
gem 'jbuilder', '~> 2.5'
gem 'jquery-rails', '~> 4.3.1'
gem 'bootstrap-sass', '~> 3.3.7'
gem 'kaminari', '~> 1.0.1'
gem 'turbolinks', '~> 5.0.1'
gem 'jbuilder', '~> 2.6'
gem 'cocoon', '~> 1.2.9'
gem 'unitwise', '~> 2.0.0'

View File

@ -1,59 +1,59 @@
GEM
remote: https://rubygems.org/
specs:
actioncable (5.0.0)
actionpack (= 5.0.0)
nio4r (~> 1.2)
actioncable (5.0.2)
actionpack (= 5.0.2)
nio4r (>= 1.2, < 3.0)
websocket-driver (~> 0.6.1)
actionmailer (5.0.0)
actionpack (= 5.0.0)
actionview (= 5.0.0)
activejob (= 5.0.0)
actionmailer (5.0.2)
actionpack (= 5.0.2)
actionview (= 5.0.2)
activejob (= 5.0.2)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.0.0)
actionview (= 5.0.0)
activesupport (= 5.0.0)
actionpack (5.0.2)
actionview (= 5.0.2)
activesupport (= 5.0.2)
rack (~> 2.0)
rack-test (~> 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.0.0)
activesupport (= 5.0.0)
actionview (5.0.2)
activesupport (= 5.0.2)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
activejob (5.0.0)
activesupport (= 5.0.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (5.0.2)
activesupport (= 5.0.2)
globalid (>= 0.3.6)
activemodel (5.0.0)
activesupport (= 5.0.0)
activerecord (5.0.0)
activemodel (= 5.0.0)
activesupport (= 5.0.0)
activemodel (5.0.2)
activesupport (= 5.0.2)
activerecord (5.0.2)
activemodel (= 5.0.2)
activesupport (= 5.0.2)
arel (~> 7.0)
activesupport (5.0.0)
activesupport (5.0.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
arel (7.1.2)
autoprefixer-rails (6.5.0)
arel (7.1.4)
autoprefixer-rails (6.7.7.1)
execjs
bcrypt (3.1.11)
blankslate (3.1.3)
bootstrap-sass (3.3.7)
autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4)
builder (3.2.2)
byebug (9.0.5)
builder (3.2.3)
byebug (9.0.6)
cocoon (1.2.9)
coderay (1.1.1)
concurrent-ruby (1.0.2)
concurrent-ruby (1.0.5)
database_cleaner (1.5.3)
debug_inspector (0.0.2)
diff-lcs (1.2.5)
diff-lcs (1.3)
erubis (2.7.0)
execjs (2.7.0)
factory_girl (4.7.0)
@ -61,11 +61,11 @@ GEM
factory_girl_rails (4.7.0)
factory_girl (~> 4.7.0)
railties (>= 3.0.0)
ffi (1.9.14)
ffi (1.9.18)
formatador (0.2.5)
globalid (0.3.7)
activesupport (>= 4.1.0)
guard (2.14.0)
guard (2.14.1)
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
lumberjack (~> 1.0)
@ -79,18 +79,27 @@ GEM
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
i18n (0.7.0)
jbuilder (2.6.0)
activesupport (>= 3.0.0, < 5.1)
i18n (0.8.1)
jbuilder (2.6.3)
activesupport (>= 3.0.0, < 5.2)
multi_json (~> 1.2)
jquery-rails (4.1.1)
jquery-rails (4.3.1)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
kaminari (0.17.0)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
libv8 (3.16.14.15)
kaminari (1.0.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.0.1)
kaminari-activerecord (= 1.0.1)
kaminari-core (= 1.0.1)
kaminari-actionview (1.0.1)
actionview
kaminari-core (= 1.0.1)
kaminari-activerecord (1.0.1)
activerecord
kaminari-core (= 1.0.1)
kaminari-core (1.0.1)
libv8 (3.16.14.19)
liner (0.2.4)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
@ -98,7 +107,7 @@ GEM
ruby_dep (~> 1.2)
loofah (2.0.3)
nokogiri (>= 1.5.9)
lumberjack (1.0.10)
lumberjack (1.0.11)
mail (2.6.4)
mime-types (>= 1.16, < 4)
memoizable (0.4.2)
@ -108,65 +117,63 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_portile2 (2.1.0)
minitest (5.9.1)
minitest (5.10.1)
multi_json (1.12.1)
nenv (0.3.0)
nio4r (1.2.1)
nokogiri (1.6.8)
nio4r (2.0.0)
nokogiri (1.7.1)
mini_portile2 (~> 2.1.0)
pkg-config (~> 1.1.7)
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
parslet (1.7.1)
blankslate (>= 2.0, <= 4.0)
pg (0.18.4)
pkg-config (1.1.7)
pg (0.20.0)
pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
puma (3.6.0)
puma (3.8.2)
rack (2.0.1)
rack-test (0.6.3)
rack (>= 1.0)
rails (5.0.0)
actioncable (= 5.0.0)
actionmailer (= 5.0.0)
actionpack (= 5.0.0)
actionview (= 5.0.0)
activejob (= 5.0.0)
activemodel (= 5.0.0)
activerecord (= 5.0.0)
activesupport (= 5.0.0)
rails (5.0.2)
actioncable (= 5.0.2)
actionmailer (= 5.0.2)
actionpack (= 5.0.2)
actionview (= 5.0.2)
activejob (= 5.0.2)
activemodel (= 5.0.2)
activerecord (= 5.0.2)
activesupport (= 5.0.2)
bundler (>= 1.3.0, < 2.0)
railties (= 5.0.0)
railties (= 5.0.2)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.1)
actionpack (~> 5.x)
actionview (~> 5.x)
activesupport (~> 5.x)
rails-dom-testing (2.0.1)
rails-dom-testing (2.0.2)
activesupport (>= 4.2.0, < 6.0)
nokogiri (~> 1.6.0)
nokogiri (~> 1.6)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
railties (5.0.0)
actionpack (= 5.0.0)
activesupport (= 5.0.0)
railties (5.0.2)
actionpack (= 5.0.2)
activesupport (= 5.0.2)
method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (11.3.0)
rb-fsevent (0.9.7)
rb-inotify (0.9.7)
rake (12.0.0)
rb-fsevent (0.9.8)
rb-inotify (0.9.8)
ffi (>= 0.5.0)
ref (2.0.0)
rspec (3.5.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-core (3.5.3)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
@ -183,8 +190,8 @@ GEM
rspec-mocks (~> 3.5.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
ruby_dep (1.4.0)
sass (3.4.22)
ruby_dep (1.5.0)
sass (3.4.23)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
sass (~> 3.1)
@ -194,26 +201,26 @@ GEM
shellany (0.0.1)
signed_multiset (0.2.1)
slop (3.6.0)
sprockets (3.7.0)
sprockets (3.7.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.0)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.3.11)
therubyracer (0.12.2)
libv8 (~> 3.16.14.0)
sqlite3 (1.3.13)
therubyracer (0.12.3)
libv8 (~> 3.16.14.15)
ref
thor (0.19.1)
thread_safe (0.3.5)
tilt (2.0.5)
thor (0.19.4)
thread_safe (0.3.6)
tilt (2.0.7)
turbolinks (5.0.1)
turbolinks-source (~> 5)
turbolinks-source (5.0.0)
tzinfo (1.2.2)
tzinfo (1.2.3)
thread_safe (~> 0.1)
uglifier (3.0.2)
uglifier (3.1.11)
execjs (>= 0.3.0, < 3)
unitwise (2.0.0)
liner (~> 0.2)
@ -225,7 +232,7 @@ GEM
activemodel (>= 5.0)
debug_inspector
railties (>= 5.0)
websocket-driver (0.6.4)
websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
@ -234,28 +241,28 @@ PLATFORMS
DEPENDENCIES
bcrypt (~> 3.1.11)
bootstrap-sass (~> 3.3.6)
bootstrap-sass (~> 3.3.7)
byebug
cocoon (~> 1.2.9)
database_cleaner (~> 1.5.3)
factory_girl_rails (~> 4.7.0)
guard (~> 2.14.0)
guard-rspec
jbuilder (~> 2.5)
jquery-rails (~> 4.1.1)
kaminari (~> 0.17.0)
pg (~> 0.18.4)
jbuilder (~> 2.6)
jquery-rails (~> 4.3.1)
kaminari (~> 1.0.1)
pg (~> 0.20.0)
puma
rails (= 5.0.0)
rails (= 5.0.2)
rails-controller-testing
rspec-rails (~> 3.5.0)
sass-rails (~> 5.0)
sqlite3
therubyracer
turbolinks (~> 5.0.0)
turbolinks (~> 5.0.1)
uglifier (>= 1.3.0)
unitwise (~> 2.0.0)
web-console (~> 3.3.1)
BUNDLED WITH
1.13.1
1.14.6

View File

@ -3,6 +3,31 @@
$(document).on("turbolinks:load", function() {
$(".recipe-view ul.ingredients").checkable();
$(".recipe-view ol.steps").checkable();
var $searchBtn = $("#recipe_index_search_button");
if ($searchBtn.length) {
var $form = $("#search_form");
var $nameInput = $("#name_search");
var $tagsInput = $("#tags_search");
$form.submit(function() {
$("#criteria_name").val($nameInput.val());
$("#criteria_tags").val($tagsInput.val());
});
$searchBtn.click(function(evt) {
$form.submit();
});
$nameInput.add($tagsInput).on('keydown', function(evt) {
if (evt.which == 13) {
console.log('keydown enter pressed');
$form.submit();
}
});
}
});
})(jQuery);

View File

@ -1,4 +1,5 @@
class Recipe < ApplicationRecord
include TokenizedLike
has_many :recipe_ingredients, -> { order :sort_order }, inverse_of: :recipe, dependent: :destroy
has_many :recipe_steps, -> { order :sort_order }, inverse_of: :recipe, dependent: :destroy
@ -9,7 +10,6 @@ class Recipe < ApplicationRecord
scope :undeleted, -> { where('deleted <> ? OR deleted IS NULL', true) }
scope :not_log, -> { where('is_log <> ? OR is_log IS NULL', true) }
scope :active, -> { undeleted.not_log }
scope :for_criteria, ->(criteria) { active.order(criteria.sort_column => criteria.sort_direction).page(criteria.page).per(criteria.per) }
accepts_nested_attributes_for :recipe_ingredients, allow_destroy: true
accepts_nested_attributes_for :recipe_steps, allow_destroy: true
@ -104,6 +104,21 @@ class Recipe < ApplicationRecord
copy
end
def self.for_criteria(criteria)
query = active.order(criteria.sort_column => criteria.sort_direction).page(criteria.page).per(criteria.per)
if criteria.name.present?
query = query.matches_token(:name, criteria.name)
end
if criteria.tags.present?
tags = Tag.by_name(criteria.tags.split)
query = query.where(id: tags.joins(:recipes).pluck('recipes.id'))
end
query
end
private
def calculate_nutrition_data

View File

@ -1,6 +1,8 @@
class Tag < ApplicationRecord
include TokenizedLike
has_and_belongs_to_many :recipes
scope :by_name, ->(names) { where(lowercase_name: Array.wrap(names).map { |n| n.downcase }) }
validates :name, presence: true, length: {maximum: 250}, uniqueness: { case_sensitive: false }

View File

@ -2,13 +2,13 @@ module ViewModels
class RecipeCriteria
SORT_COLUMNS = :created_at, :name, :rating, :total_time
PARAMS = [:sort_column, :sort_direction, :page, :per, :name, :tags]
attr_writer :sort_column, :sort_direction
attr_writer :page, :per
attr_accessor *PARAMS
def initialize(params = {})
def initialize(params = nil)
params ||= {}
([:sort_column, :sort_direction, :page, :per]).each do |attr|
PARAMS.each do |attr|
setter = "#{attr}="
if params[attr]
self.send(setter, params[attr])
@ -17,31 +17,29 @@ module ViewModels
end
def sort_column
@sort_column ||= SORT_COLUMNS.first
@sort_column = @sort_column.to_sym
unless SORT_COLUMNS.include? @sort_column
@sort_column = SORT_COLUMNS.first
end
@sort_column
default(@sort_column.to_s.to_sym, SORT_COLUMNS.first, ->(v) {SORT_COLUMNS.include?(v)} )
end
def sort_direction
@sort_direction ||= :asc
@sort_direction = @sort_direction.to_sym
unless [:asc, :desc].include? @sort_direction
@sort_direction = :asc
end
@sort_direction
default(@sort_direction.to_s.to_sym, :desc, ->(v) {[:asc, :desc].include?(v)} )
end
def page
@page.to_i || 1
default(@page, 1, ->(v) { v.to_i > 0 })
end
def per
@per.to_i || 50
default(@per, 50, ->(v) { v.to_i > 0 })
end
protected
def default(val, default_val, valid_proc)
if val.blank? || !valid_proc.call(val)
default_val
else
val
end
end
end

View File

@ -5,16 +5,21 @@
<h1>Recipes</h1>
</div>
<% if @recipes.empty? %>
<p>No Recipes</p>
<% else %>
<% if current_user? %>
<%= link_to 'New Recipe', new_recipe_path, class: 'btn btn-default' %><br/>
<% end %>
<%= paginate @recipes %>
<%= form_for(@criteria, as: :criteria, url: recipes_path, method: :get, html: {id: 'search_form'}) do |f| %>
<%= f.hidden_field :sort_column %>
<%= f.hidden_field :sort_direction %>
<%= f.hidden_field :page %>
<%= f.hidden_field :per %>
<%= f.hidden_field :name %>
<%= f.hidden_field :tags %>
<% end %>
<div class="table-responsive">
<table class="recipe-table table table-striped table-hover">
<thead>
@ -25,9 +30,16 @@
<th>Yields</th>
<th><%= index_sort_header('Time', :total_time, @criteria) %></th>
<th><%= index_sort_header('Created', :created_at, @criteria) %></th>
<% if current_user? %>
<th></th>
<% end %>
</tr>
<tr>
<th><%= text_field_tag('name_search', @criteria.name) %></th>
<th><%= text_field_tag('tags_search', @criteria.tags) %></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th><button id="recipe_index_search_button" class="btn btn-sm btn-default">Search</button></th>
</tr>
</thead>
@ -46,8 +58,9 @@
<td><%= recipe.yields %></td>
<td><%= recipe_time(recipe) %></td>
<td><%= timestamp(recipe.created_at) %></td>
<% if current_user? %>
<td>
<% if current_user? %>
<%= link_to new_recipe_log_path(recipe), class: 'btn btn-sm btn-primary' do %>
<span class="glyphicon glyphicon-copy"></span>
<% end %>
@ -57,18 +70,20 @@
<%= link_to recipe, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-sm btn-danger' do %>
<span class="glyphicon glyphicon-remove"></span>
<% end %>
</td>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<%= paginate @recipes %>
<% if @recipes.empty? %>
<p>No Recipes</p>
<% end %>
<%= paginate @recipes %>
<br>
<% if current_user? %>